Vectorでヒープエラーが出る

このQ&Aのポイント
  • プログラム中のループ処理において、ヒープエラーが発生しています。
  • 2回目のループ時に同じポインタを指すバッファが原因です。
  • 問題の解決方法について教えてください。
回答を見る
  • ベストアンサー

Vectorでヒープエラーが出る

下記のプログラムで、2回目のループを抜けたところでヒープエラーが 出てしまいます。 2回目のループ時にv[0]とv[1]の中のbuffが同じポインタを指してしまうことが原因のようですが、なぜ同じポインタを指してしまうのかがわかりません。 どうしたらこの問題が解決するのでしょうか? 以上、よろしくお願いします。 #include "CBuff.h" main(){ vector<CBuff> v; char *tmpstr; for (int i = 0; i < 3; i++){ if (i == 0){ tmpstr = new char[5]; memcpy(tmpstr, "aaaa", 5); }else if(i == 1){ tmpstr = new char[6]; memcpy(tmpstr, "bbbbb", 6); }else { tmpstr = new char[7]; memcpy(tmpstr, "cccccc", 7); } CBuff cb; cb.setBuff(tmpstr, strlen(tmpstr) + 1); v.push_back(cb); delete [] tmpstr; } } 【CBuff.h】 #pragma once class CBuff{ char *buff; public: CBuff(); ~CBuff(); void setBuff(char*, size_t); }; CBuff::CBuff(){ buff = NULL; } CBuff::~CBuff(){ if (buff != NULL){ delete [] buff; buff = NULL; } } void CBuff::setBuff(char *input, size_t size){ buff = new char[size]; memcpy(buff, input, size); }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

 こんばんは。  先ずは、CBuffクラスのデストラクタを以下の様にして、実行してみましょう。 CBuff::~CBuff() { ::printf("[CBuff::~CBuff() call] [delete pointer] %p\n", buff); if (buff != NULL) { delete [] buff; buff = NULL; } }  デストラクタで、同一のポインタが削除されているのが分かります。  理由はコピーコンストラクタが無い事です。コピーなどした覚えは無いと思うかもしれませんが、実は  v.push_back(cb);  の奥深くでは、std::allocator<T>で割り当てたメモリに対して、クラスcbをコピーしています(プレースメントnew)。  結論としては、コピーコンストラクタと代入演算子をしっかり書く、という事です。  コピーコンストラクタ内の取り扱いも色々な方式が有るのですが、簡単なディープコピーにしておきます。  詳しく知りたいのであるならば、それなりに突っ込んだ書籍等をご覧になられる事をお勧めいたします。 //コピーコンストラクタ CBuff::CBuff(const CBuff& rhs) : buff(NULL) { if(!rhs.buff)return; const std::size_t len = ::strlen(rhs.buff) + 1; this->buff = new char[len]; std::copy(rhs.buff, rhs.buff + len, this->buff); } //代入演算子 CBuff& CBuff::operator=(const CBuff& rhs) { if(this != &rhs) { this->~CBuff(); new (this) CBuff(rhs); } return *this; }  しかし、動かすだけなら此れで良いのですが、実際にはCBuffを作成する必要は無いと言えます。  std::stringを使用すれば良い訳です。 #define ARRAYCOUNT(a) (sizeof(a) / sizeof(a[0])) #include<string> int main() { std::vector<std::string> v; const char* arrPsz[] = {"aaaa", "bbbbb", "cccccc"}; for (int i = 0; i < ARRAYCOUNT(arrPsz); i++) { v.push_back(arrPsz[i]); ::printf("%s\n", v.back()); } return 0; }

関連するQ&A

  • ポインターについて

    http://oshiete1.goo.ne.jp/kotaeru.php3?q=2352832 で、質問させて頂いた者です。 ポインターの使い方について 理解できないところがありましたので 新しく質問をさせて頂きました。 ----------- ↓構造体の型を宣言しています typedef struct douken_ { char tiku[11]; char ken[9]; } douken; int main(void){ FILE *fp; ↓変数を宣言 douken dou [100]; ・ ・ ・ while (fgets(buff,sizeof buff,fp) != NULL){ ファイルから読み込んだデータを構造体に格納 memcpy(&dou[i].tiku ,buff,10); memcpy(&dou[i].ken ,buff+10,10); 【ここが問題】 現データと全データを比較する if (strcmp(dou[i].tiku , dou[i-1].tiku)){ ----------- if文で現データと全データを比較する時に、 実数だと正常に動くのですが ポインターで指定すると 警告が出てしまいます。 if (strcmp(&dou[i].tiku , &dou[i-1].tiku)){ とすると >警告 W8075 kadai3-2.c 33: 問題のあるポインタの変換(関数 main ) という警告が出てしまうのです。 どうしてポインターで指定すると 警告が出るのかが分からないのです。 (memcpyではファイルから読み込んだデータを 構造体に格納するときはポインターで指定しているのに…) ご教授して頂けたら幸いです。

  • if文で…

    いつもお世話になっております。 ------------------------ typedef struct douken_ { char tiku[11]; char ken[9]; } douken; int main(void){ FILE *fp; douken dou [100]; char buff [18 /* douken */ + 2 /* CrLf(\n\r) */ + 1 /* \0 */]; int i; i = 0; fp = fopen("ex3.fil","rb"); if ( fp == 0 ){ printf("can't open\n"); exit(1); } memset (dou , '\0' , sizeof dou); memset (buff, '\0' , sizeof buff); 問題はここから----------------- while (fgets(buff,sizeof buff,fp) != NULL){ memcpy(&dou[i].tiku ,buff,10); memcpy(&dou[i].ken ,buff+10,10); if (&dou[i].tiku == &dou[i-1].tiku){ printf("%s %s",&dou[i-1].tiku,&dou[i].tiku,&dou[i].ken);} else{ printf("-----------------------"); } ------------------------ 上記のプログラムでは ファイルから読み込んだデータを 構造体に格納して if文で現データと全データを 比較するという処理をしています。(つもり) 構造体に格納するところまでは 出来たのですが if文のところが上手く行きません。 例えば 現データ(tiku)関東地区 前データ(tiku)関東地区 と、同じ場合は 関東地区 東京 と、表示したいのに ----------- と、elseの処理をしてしまいます。 対処方法をご存じでしたら、 ご教授して頂けたら幸いです。

  • cygwinを使ってcsvファイルを読み込み、出力させようとしています

    cygwinを使ってcsvファイルを読み込み、出力させようとしています。 とりあえず、読み込みのみのプログラムを作成し、 実行させてみたのですが(run ファイル名.csv と入力) 「Error: could not start C:\cygwin\home\ユーザー名ファイル名.csv」 と出力され、読み込みができず、困っています。 プログラム初心者です。 恐縮ですがご回答よろしくお願いします。 以下に、読み込みプログラムとcsvファイルを記載します。 (プログラムは拾い物です。) <プログラム> #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("comand error nyuuryoku keishiki\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("can not open file[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("data error[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("error(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("error(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("error(3)\n"); break; } if(*wp != '\0'){ printf("error(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); } <csvファイル> 1,2,3 11,12,13 21,22,23

  • ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込

    ネットで落ちていた「Excelで作ったデータ(CSVファイル)の読み込みプログラム」をそのままコンパイルして実行しようと思ったのですが、 sample.c: In function 'main': sample2.c:9: warning: return type of 'main' is not 'int' と、表示されてしまいます。 プログラミング初心者なので、どこが間違っているのかわかりません。 回答またはアドバイスの程、よろしくお願いいたします。 ネットで落ちていたプログラムを以下に記載します。 sample2.c #include <stdio.h> #define MAX_ITEM_SIZE 100 #define MAX_LINE_SIZE 1024 char *GetCSVItem(char *wp, char *buff, int size); void main(int argc, char *argv[]) { FILE *fp; char buff[MAX_LINE_SIZE], *wp, item[3][MAX_ITEM_SIZE]; int i1, len; if(argc != 2){ printf("コマンドの入力形式が間違っています.\n"); return; } fp = fopen(argv[1], "r"); if(fp == NULL){ printf("ファイルがオープンできません[%s].\n", argv[1]); return; } for(;;){ if(fgets(buff, MAX_LINE_SIZE, fp) == NULL) break; len = strlen(buff); if(len == 0 || buff[len-1] != '\n'){ if(feof(fp) == 0){ printf("データが不正です[%s].\n", buff); return; } } buff[len-1] = '\0'; wp = buff; if((wp = GetCSVItem(wp, item[0], MAX_ITEM_SIZE)) == NULL){ printf("エラー(1)\n"); break; } if((wp = GetCSVItem(wp, item[1], MAX_ITEM_SIZE)) == NULL){ printf("エラー(2)\n"); break; } if((wp = GetCSVItem(wp, item[2], MAX_ITEM_SIZE)) == NULL){ printf("エラー(3)\n"); break; } if(*wp != '\0'){ printf("エラー(4)\n"); break; } for(i1 = 0; i1 < 3; i1++){ printf("%d:%s\n", i1+1, item[i1]); } } fclose(fp); } char *GetCSVItem(char *wp, char *buff, int size) { int i1; buff[0] = '\0'; while(*wp == ' ' || *wp == '\t') wp++; if(*wp == '\0'){ return(NULL); } for(i1 = 0; i1 < MAX_ITEM_SIZE; i1++, wp++){ if(i1 >= size) return(NULL); buff[i1] = *wp; if(*wp == '\0'){ buff[i1] = '\0'; return(wp); } if(*wp == ','){ wp++; buff[i1] = '\0'; break; } } return(wp); }

  • newについて

    newを使った場合、3バイト分確保したつもりでしたが、7バイト?になります。どうしてでしょうか? newした場合はdeleteをしないといけませんが、deleteした後にNULLで初期化する意味はあるのでしょうか? CとC++が混在?(newはC++かな?)しているソースなのですが、 現場(クリティカルな開発)ではこういう書き方はNGでしょうか? 組み込み系のお仕事をされている方の意見も聞きたいです。 #include <string.h> void main(void){ char *cstr = new char [3]; printf("%d\n", strlen(cstr)); // 3を期待していたのですが、7になります。 if (cstr != NULL){ delete cstr; cstr = NULL; } }

  • VC++でのメールの添付ファイル受信

    http://www.masukawa.co.jp/sdk/40.html のサイトを参考にしてソースを組んでいます。 ですが BOOL Pop3RecvDataToFile(SOCKET sock, int i, char *filename) { char *get, tmp, buff[BUFF_SIZE]; int size, pos; FILE *fp; if (!SockCmd1(sock, "RETR %d", i, buff, "+OK")) return FALSE; if ((fp = fopen(filename, "wb")) == NULL) return FALSE; tmp = '\0'; pos = 0; for (;;) { size = recv(sock, buff, BUFF_SIZE, 0); for (get=buff; get<(buff+size); get++) { if (*get=='\0' || *get=='\r') continue; if (++pos == 1) { if (*get != '\n') { tmp = *get; continue; } } else if (pos == 2) { if (tmp=='.' && *get=='\n') goto FINISH; if (tmp!='.' || *get!='.') fputc(tmp, fp); } fputc(*get, fp); if (*get == '\n') pos = 0; } } FINISH: fclose(fp); return TRUE; } のfor分で無限ループしています。 その理由がわかりません。どうすればよいでしょうか?

  • 多次元配列の new 2

    追加の質問ですみません^^; char の8個の配列へのポインタの配列を new する場合などは、以下のサンプルのように typedef しないとかけないんでしょうかね?たとえば、  char (**bb)[8] = new (char (*)[8])[8]; 書きたいように思いますが、これは文法違反ですし・・・^^; ==== サンプル:(iostream の初期化時に、定義した new が呼び出されるかもしれないことを一応考慮して、stdio の関数を使っています^^) #include <new> #include <stdlib.h> #include <stdio.h> void *operator new(std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new(): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete(void *p) { fprintf(stderr, "::delete(): %p\n", p); if (p) free(p); } void *operator new[](std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new[](): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete[](void *p) { fprintf(stderr, "::delete[](): %p\n", p); if (p) free(p); } int main() { typedef char (*T)[8]; char (**b)[8] = new T[8]; delete[] b; } ==== % ./a.exe ::new[](): 0x6e01b0 32 ::delete[](): 0x6e01b0

  • Winsockを用いてデータを交互に送信しあいたい

    チャットプログラムではないのですが、チャットプログラムのソースが参考になると思いネットで調べて見ましたが見つからなかったので質問させていただきます。 したいのは、.rarなどの圧縮されたファイル(サイズはGB単位)の送信(TCP)です。 トータルのファイルサイズとファイル名をBYTE配列に書き込む BYTE配列のサイズを送信後、BYTE配列を送信 (とりあえずここでトータルサイズを4MB(4×1024×1024)で割った商をQ、余りをRと置いておく) ファイルをバイナリ読み込みモードで開く 受け取ったという合図を受け取ったらファイルの先頭から4MB読み込んでBYTE配列に入れて送信 受け取ったという合図を受け取ったら続きから4MB読み込んでBYTE配列に入れて送信 ↑を先頭の分も合わせてQ回繰り返す。 受け取ったという合図を受け取ったら続きからRバイト読み込んでBYTE配列に入れて送信 ファイルを閉じる としたのですが、 ファイルの先頭から4MBは送信できているようなのですが、そこから先に進みません。 具体的には、4MBの受信したという合図を送っても、send関数が-1を返すようです プログラムは以下の通りです Server Winsockの設定やファイルのトータルサイズ云々なので略 listen( RecvSock, 5 ); fp = fopen( FileName, "rb" ); int TotalSend = 0; int i = -1; SendSock = accept(RecvSock, (struct sockaddr *)&Send, &len);//コメントアウトを外す場合はこれはコメントアウト while(1) { //SendSock = accept(RecvSock, (struct sockaddr *)&Send, &len); if( i == -1 ) { send( SendSock, (char *)&FileSize, 4, 0 ); //↓の配列サイズを入れたBYTE配列 send( SendSock, (char *)Buff, Size, 0 );//トータルファイルサイズとファイル名 delete []Buff;//BYTE *Buff = new BYTE[FileSize]としたため } //フラグ受信 { recv( SendSock, (char *)&i, 4, 0 ); } if( i == Q ) { fread( SendBuff, R, 1, fp ); while( TotalSend < R ) { TotalSend += send( SendSock, (char *)&SendBuff[TotalSend], R-TotalSend, 0 ); } } else if( i != -1 ) { fread( SendBuff, SendSize, 1, fp );// SendSizeは4*1024*1024の値を#define while( TotalSend < SendSize ) { TotalSend += send( SendSock, (char *)&SendBuff[TotalSend], SendSize-TotalSend, 0 ); } } printf( "%d/%d\n", i, Q ); } Client //Winsockの設定やファイルのトータルサイズ云々なので略 FILE *fp = fopen( FileName, "ab" ); int Total = 0; for( int i=0 ; i<=Q ; i++ ) { //connect( Sock, (struct sockaddr *)&Addr, sizeof(Addr) ); int Error = FileRecv( Sock, i, Q, R, fp ); if( Error == -1 ) { i--;//エラーが出るのでどこでエラーが出るのか見るために追加 } else { printf( "%d/%d\n", i, Q ); } } int FileRecv( SOCKET Sock, int Flag, int Q, int R, FILE *fp ) { //Winsockの設定をコメントアウト中。外した場合、引数のSOCKET Sockは消す int Total = 0; //フラグ送信 { BYTE buff[4]; memmove( buff, &Flag, 4 ); int Error = send( Sock, (char *)buff, 4, 0 ); if( Error == -1) { return -1; } } if( Flag == Q ){ Buff = new BYTE[R]; memset( Buff, 0, sizeof(Buff) ); while( Total < R ) { Total += recv( Sock, (char *)&Buff[Total], R-Total, 0 ); } fwrite( Buff, R, 1, fp ); delete []Buff; } else { Buff = new BYTE[SendSize]; memset( Buff, 0, sizeof(Buff) ); while( Total < SendSize ) { Total += recv( Sock, (char *)&Buff[Total], SendSize-Total, 0 ); if( Total == -1 ) { delete []Buff; return -1; } } fwrite( Buff, SendSize, 1, fp ); delete []Buff; } // closesocket(Sock); // WSACleanup(); return 1; } 毎回切断してもう一度接続しなおすようにしても(コメントアウトを外す)結果(エラー部)は変わりません。 どこが悪いのか見ていただけないでしょうか?

  • クイックソート

    実行時にエラーが出てしまいます。問題点がわかる方お願いします。(インクルード略、800字に収まらなかったので問題があると思われる部分だけ書きます。)ちなみにエラーは外部参照~という感じです。 typedef struct in_data { char bango[No_SIZE]; int ki; }RD; RD *q_sort(RD a[],int n0,int nn); void swap(RD *pa,RD *pb); void main() { FILE *fpa; FILE *fpb; char in_buff[BUFF_SIZE]; RD buff[ARRY_SIZE]; int i; fpa = fopen("data.TXT","r"); for(i=0;i < ARRY_SIZE;i++){ fgets(in_buff,BUFF_SIZE,fpa); strncpy(buff[i].bango,in_buff,No_SIZE); buff[i].bango[No_SIZE] = '\n'; buff[i].ki = atoi(&in_buff[No_SIZE]); } fclose(fpa); q_sort(buff,0,ARRY_SIZE-1); fpb = fopen("result.TXT","w"); for(i=0;i < ARRY_SIZE ; i++) fprintf(fpb,"%*s %*d\n",No_SIZE,buff[i].bango, season_SIZE,buff[i].ki); fclose(fpb); } RD *qsort(RD a[],int n0,int nn) { char x; int i,j; if(nn - n0 == 1){ if(strcmp(a[n0].bango,a[nn].bango)>0) swap(&a[n0],&a[nn]); } else if (nn - n0 >1){ x = (n0+nn)/2;

  • このプログラムのアルゴリズムを教えていただけませんか?

    ファイルlog.txtの文章中からIPアドレスを抜き出し、ip.txtに書き込むというプログラムです。文章は 日付 http attempt from xxxx.xxxx.xxxx.xxxx:ポート番号とう具合に並んでいます。 /* ・・・ from IP:portなフォーマットが前提*/ より下でIPを検出しているとおもうのですが、具体的にどういう手順で検出しているのかわかりません。 どうか宜しくお願いします。 #include <stdio.h> #include <string.h> void addLine(const char*,FILE*); char* getFromIP(const char*,char*); int main() { FILE* pFileA = fopen("log.txt","rt"); char buff[256]; if(pFileA){ FILE* pFileB = fopen("ip.txt","wt"); if(pFileB){ for(;fgets(buff,256,pFileA) != NULL;){ char buff2[32] = {'\0'}; addLine(getFromIP(buff,buff2),pFileB); } fclose(pFileB); } fclose(pFileA); } return 0; } /* ・・・ from IP:portなフォーマットが前提*/ char* getFromIP(const char* line,char* buff){ const size_t length = strlen(line); size_t top,back = length-1,i,k; for(back = length-1;line[back] != ':';--back); for(i=0,top = back - 1;i<3;++i){ for(;line[top] != '.';--top); } for(;line[top-1] != ' ';--top); for(i=top,k=0;i<back;buff[k++] = line[i++]); return buff; } void addLine(const char* str,FILE* pFile){ char buff[1024]; sprintf(buff,"%s\n",str); fputs(buff,pFile); }

専門家に質問してみよう