realloc関数でメモリエラー

このQ&Aのポイント
  • Microsoft VS 6.0 で作成したプログラムでrealloc関数を使用すると、メモリエラーが発生してしまいます。
  • realloc関数を複数回使用すると、他のメモリ領域が破壊される可能性があります。
  • realloc関数を使用せずにmalloc関数のみを使用すると、メモリエラーは発生しません。
回答を見る
  • ベストアンサー

realloc関数でメモリエラー

いつもお世話になります。 今、Microsoft VS 6.0 でrealloc関数を使用したプログラムを作成した所、 メモリエラーが発生してしまいました。 どうも、調査を行なっていくと、realloc関数を何回か使用していくと、 別のメモリ領域を破壊(?)しているように思えます。 そのような現象って、他の方々も発生した事があるのでしょうか?? それとも何か落とし穴が??? どなたか情報をもっている方、是非是非お願いします。 ちなみに、reallocを使用せず、malloc関数のみで作成したプログラムでは 発生してません。 ---------------- 【reallocを使用していて作成した関数】   ファイルを読み込み、1件読むたびにrealloc関数でエリア拡張    (最初の1件目はmalloc関数にてエリア確保、2件目以降realloc使用) 【原因】   ポインタ変数の内容(アドレス値)が変更されている事が発覚      →おかしくなったエリアを参照しようとしてメモリエラーが発生       ↓   変更された個所を選定していくと、   「realloc」関数を使用後変更されている事が発覚      ※変更されていたポインタ変数は、「realloc」関数使用時には       全く参照もしていない変数で、ロジック上値を変更するような事は       なかった       ↓   「realloc」関数を使用すると常に発生しているわけではない事は確認済     (たまに発生 ←メモリ領域へのアロケートなので取得するエリアによって発生すると推測)       ↓   同様のロジックを予め件数を数えた後、   「malloc」関数を使用すると発生しない事は確認済

  • KZY
  • お礼率50% (1/2)

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

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

void * __cdecl realloc(void *, size_t); reallocは、引数で渡した先頭アドレスと、戻される再確保された領域の先頭アドレスは異なることがあります。 返されたアドレスを使って後の処理をしていますか?

KZY
質問者

補足

回答ありがとうございます。 質問するのに最大文字制限があって書ききれてませんでした。 再確保したアドレスを使用して、そのあとの処理は行ってます。 途中省略してますが、こんな感じです。 --------------------------- for( i = 0 ; ; i++) { *pt2 = realloc( *pt2 ,sizeof(構造体) * (i+1) ); } これで、デバッグログを出力すると、、、 --------------------------- 【デバッグ情報】 pt1:変更されたポインタ変数 pt2:reallocによって再確保時使用ポインタ(ダブルポインタ) pt1->item1 :pt1の格納内容 pt1 <-内容 :pt1の格納しているアドレス値を表示 pt2 <-アドレス :pt2自身のアドレス値を表示 pt2 <-ア<-内容 :pt2の格納しているアドレス値を表示 pt2 <-ア<-ア :pt2の格納しているアドレス値が指し示す内容を表示 【ログ内容】 ---------- realloc前 pt1->item1 =[01]: pt1 <-アドレス =86733120: pt1 <-内容 =86781256: pt2 <-アドレス =1150176: pt2 <-ア<-内容 =92020460: pt2 <-ア<-ア =75746000: ---------- realloc後 pt1->item1 =[01]: pt1 <-アドレス =86733120: pt1 <-内容 =86781256: pt2 <-アドレス =1150176: pt2 <-ア<-内容 =92020460: pt2 <-ア<-ア =75746000: ※通常はこのようにpt1は何の影響も受けない ---------- realloc前 pt1->item1 =[01]: pt1 <-アドレス =86733120: pt1 <-内内容 =86781256: pt2 <-アドレス =1150176: pt2 <-ア<-内容 =92020460: pt2 <-ア<-ア =75746000: ---------- realloc後 pt1->item1 =[]: pt1 <-アドレス =86733120: pt1 <-内容 =959591986: pt2 <-アドレス =1150176: pt2 <-ア<-内容 =92020460: pt2 <-ア<-ア =86733120:   ※realloc関数で再確保された領域がpt1のアドレスを上書きしている    その為pt1の指し示す内容が変更されている と、こんな感じになってしまいます。。。 一体なぜ??? とハテナが一杯なんです。。。

その他の回答 (1)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

すいません。 pt1とpt2の関係はなんでしょう? pt2とはまったく関係が無いpt1が指し示す領域が破壊されているということでしょうか?

KZY
質問者

お礼

すいません。 もう一度ソースを見直した所、pt1の領域が別のソース上で 既にFreeされていました。 Freeされた元Pt1の領域にpt2が新たにアロケートをしようと した結果、見た目pt1の領域が破壊されたように見えていたようです。 アロケートは全く関係なく正常に動作していて、こちらの ソース上の問題でした。(お恥ずかしい限りです) お騒がせして申し訳ございませんでした&ご協力ありがとうございました。

KZY
質問者

補足

すいません。言葉足らずでした。 pt1とpt2は全く関係ないポインタ変数です。 なんで、realloc関数が領域を壊してるの??? て思ったのですが、、、 もう一度ソース見直してみます。。。

関連するQ&A

  • c言語のmalloc関数、またrealloc関数

    c言語のmalloc関数は確保するメモリの領域を、配列としてのみしか処理出来ないのですか。 つまり、malloc関数で確保したメモリの領域を変数、また多次元配列、また構造体としては処理出来ないのでしょうか。 c言語のrealloc関数は以前の確保したメモリの領域から、確保し直したメモリの領域の場所が変わるかもしれないという事ですが、この場合の場所が変わるという意味は、メモリの領域のアドレスが変わるという事でしょうか。 また、以前の確保したメモリの領域に代入していたデータが使用出来なくなるという事でしょうか。

  • reallocの使い方について

    C言語初心者です。malloc()で確保した領域をrealloc()にて拡張しました。以下、わからないことがあるので教えて下さい。 #include <stdio.h> #include <stdlib.h> int main(){ int *array1; array1=malloc(sizeof(int)*3); for(int i=0; i<3; i++){ *(array1+i)=i; } int *array2=array1; for(int i=0; i<3; i++){ printf("array2[%d]: %d\n", i, array2[i]); } array1=realloc(array1, sizeof(int)*5); for(int i=3; i<5; i++){ array1[i]=i; } for(int i=0; i<5; i++){ printf("array2[%d]: %d\n", i, array2[i]); } } 上記のソースコードでは、私が期待したのは array2[0]: 0 array2[1]: 1 array2[2]: 2 array2[0]: 0 array2[1]: 1 array2[2]: 2 array2[3]: 3 array2[4]: 4 なのですが、実行すると次のように表示されます。 array2[0]: 0 array2[1]: 1 array2[2]: 2 array2[0]: 0 array2[1]: 1 array2[2]: 2 array2[3]: 0 array2[4]: 1 まず最初に、array1という名前のポインタをつくり、malloc関数にて整数3つ分の領域を確保し、整数0、1、2を投入する。次に、array2という名前のポインタをつくり、array1と同じ領域を指すようにする。なので、array2にはデータを投入しなくても参照すると既に0、1、2が入っている。 次に、realloc関数にて領域を2つ追加する。追加された領域には、array1ポインタ経由で実データに整数3、4を投入する。実データが変更されたので、array2ポインタ経由でデータを参照すると、0、1、2、3、4が参照出来る、と思ったのですがそうなっていません。array1ポインタ経由で見ると、きちんと0、1、2、3、4が参照出来るのですが。。 私のreallocの理解に誤りがあれば教えて下さい。宜しくお願いします。

  • reallocについて

    reallocでのメモリの割り当てで、 buf = realloc( buf, 1024 ); のように書かれているソースがありますが、この書き方のように reallocの第1引数とreallocの帰り値を受ける変数を同じにすると reallocのエラーに対応できませんよね? それとは別に、buf = (char*)malloc(4);で下図のようになったとすると  ×××××××××××××××○○○○×  あいうえおかきくけこさしすせそたちつてと その後の buf = realloc( buf, 8 );では、[たちつて]に かぶることなく下図のようになると思います。 三角の部分は丸の部分にデータをコピーするために 完全には開放しないはずですよね。  ×○○○○○○○○××××××△△△△×  あいうえおかきくけこさしすせそたちつてと ここからさらにreallocすると、三角だった部分は下図のように reallocによる新しい領域に使われる可能性はありますか?  buf = realloc( buf, 9 );  ×△△△△△△△△×○○○○○○○○○×  あいうえおかきくけこさしすせそたちつてと 図のひらがなはアドレスを意味しています。 定幅フォントのエディタにコピーして見ていただきたいです。

  • reallocについて

    以下のソースでmallocやreallocの使い方で間違った部分があれば 指摘してください。 #include <iostream.h> #include <malloc.h> typedef unsigned char byte; main() { byte *p = (byte*)malloc(10); memcpy(p, "123456789", 9); p = (byte*)realloc(p, 5); *(p+4) = 0; printf("%s", (char*)p); p = (byte*)realloc(p, 0); return 0; } realloc(p, 5)のようにreallocでメモリブロックを10から5に 小さくしてもいいんですか? 足りなくなったメモリを増やすためのreallocしか見たことがありません。 reallocでは先頭バイトの位置が保たれていることは保証されますか? 別の言い方をすると、memcpy(p, "123456789", 9);によって 1が入ってるバイトを、reallocした後の*pが差すことが保証されていますか? もし保証されるなら、例えば上記のソースで1234と表示される 別の言い方をすると、reallocでメモリブロックの値は変更されない ことは保証されていますか?

  • ポインタのポインタとrealloc

    先程関数による動的確保について質問させていただき、ヒントを与えていただいたのですが、そこからまた疑問が生じました。 テストプログラムを作ったのですが、何やら動作がおかしいみたいです おかしい部分を抜き出したソースは次のとおりです int main() {  int **p;  int i;  p = (int **)malloc(sizeof(int *));  *p = (int *)malloc(sizeof(int));  p[0]=0;  for(i=1;i<10;i++){   *p = (int *)realloc(*p,sizeof(int)*(i+1));   *p[i] = i;  }  free(*p);  return 0; } 関数部として作りたい部分をメインにして抜き出しました。 このようにするとreallocがメモリ領域を拡張してくれなく(?)、*p[i] = i;の部分でエラー終了します。 ポインタのポインタではなく、ポインタを用いた時は正常に動作するのですが、何がまずいのでしょうか。 もし宜しければお願いいたします。 ちなみに私は学部4年生で、プログラムの使用は大学の研究用レベルです。

  • メモリ解放が必要な場合

    基本的な質問です。mallocやreallocのときはfreeが必要といわれますが、ローカル変数でポインタ型の変数を宣言したときなどもfreeしてもいいのでしょうか?splintをかけるとmallocのように動的にメモリ確保してないのにメモリリークの可能性が。。。などとエラーがでてしまってどう対応したらよいか困っています。

  • 関数にポインタを渡して動的確保する時について

    どうにも動的確保について間違っている気がするのでお尋ねいたします。 よくメモリを動的に確保する場合に私は次のようなプログラムを書きます ポインタを用意する(例えばint *p) mallocでメモリ確保 ポインタを関数に渡す(Func(p)) 関数側でreallocし、値を代入する(p=(int *)realloc(p,sizeof(int)*num)) 関数呼び出し側で、その値を使う しかし、この方法を使うとどうにも関数を呼び出した際のポインタ(p)と、reallocした後のポインタ(p)の値が違うことがあり、値が不定になることがあります。 (reallocのメモリの確保の仕方のせいでしょうか) この使い方は恐らくどこか間違っていると思うんですが、いまいち納得のいく解決策が思いつきません。 例えばポインタを引数ではなく戻り値として得ればできますが、2つ以上のポインタについてはできません。 何卒ご教授のほどをよろしくお願いいたします。

  • reallocについて

    現在、領域を拡張しながら、 ファイルを読み込んで呼び元に返却するPGを作成しています。 reallocがうまくいかないので、試しに小さいのを作って みましたが、これだとreallocの2度目で落ちます。 100文字ずつ呼んでいるので、拡張も100文字ずつ行っています。 メモリ確保に失敗なら、まだ分かるのですが、 ちょっと理由がわかりません。 reallocを複数繰り返していることも問題だと思いますが、 まずは正常に処理を流したいと考えています。 よろしくお願いします。 ~~~~~~ソース~~~~~~~~ //ファイルを読み込んでから領域を確保する #include <stdio.h> #include <string.h> #include <stdlib.h> #define BUFF 100 int main() { FILE *fp; char tmp[BUFF+1]; char *str; int len = 0; fp = fopen( "c:/test.txt" , "rb" ); if(fp ==0){ printf("ファイルがありません\n"); return -1; } //領域を初期化 str = (char *)malloc(1); memset(str,'\0',sizeof(str)); while(feof(fp)==0){ memset(tmp,'\0',sizeof(tmp)); fgets(tmp,BUFF,fp); //領域を再確保 len += BUFF+1; if(NULL == ((char *)realloc(str,len))){ printf("メモリ確保エラー"); } //読み込んだ値を変数に追加 strcat(str,tmp); } printf("文字列\n\n%s\n",str); printf("長さ:%d\n",len); fclose(fp); return 0; }

  • 動的なメモリ領域の確保

    double型変数5個分のメモリをmalloc関数により確保し,その確保した要素のアドレスを表示するように,プログラムを作る問題で、 (注)に「 %pで表示するためには,double型へのポインタ(double *)をvoid型へのポインタ(void *)にキャストする必要がある.」と書かれていたのですが、どういうことでしょうか? 以下のようでいいのでしょうか? #include<stdio.h> #include<stdlib.h> #define COUNT 5           // 動的に確保するメモリ領域数を示すマクロ定数の定義 int main(void) {  // 動的に確保するメモリ領域のアドレスを保持するポインタ変数の宣言  double * pointer;  int i;                  // for文で使用する変数の宣言  // int型変数5個分のメモリ領域を確保  pointer = (double *)malloc(sizeof(double) * COUNT);  if(pointer == NULL) {        // メモリ領域の確保が失敗した場合   printf("メモリ領域を確保できませんでした.\n");   exit(1);                // プログラムの終了  }  for(i = 0; i < COUNT; i++)   printf("%d番目のアドレスは%pです.\n", i + 1, pointer + i);  free(pointer);            // 確保したメモリ領域の解放  return 0; }

  • 配列ポインタの関数中のメモリ領域

    C初心者です。 関数中で配列ポインタを宣言する場合についての質問です。 たとえばDouble型の2次元のローカルな配列ポインタを用いる場合、 その配列要素数が100である場合は void 関数名(引数1,引数2,...){ int i; double *a[2]; for(i=0;i<2;i++){ a[i] = (double*)malloc(100*sizeof(double)); } for(i=0;i<2;i++){ free(a[i]); } } またこの値を引数1とする場合、引数1をoutとすると void 関数名(double *out,....) とし、 for(i=0;i<2;i++){ out[i] = a[i]; } とすればよいのでしょうか? もしこれがあっているとすると、つぎのような現象で困っています。 配列要素数を50000個ぐらいとし、複数の関数で、同様に mallocを用いて、配列ポインタのローカルでメモリ領域を確保しようとした場合、コンパイルは成功するのですが、その後実行すると、エラーが発生したというメッセージとともにコマンドウィンドが強制終了します。 コンパイラはVisual C++ EXpress Edition 2008です。 データサイズを小さくすると、エラーは起きません。 malloc関数で確保するメモリサイズは、関数の入力引数で定義された変数を用いて計算しており、データサイズに応じて変更されます。 よろしくお願いいたします。

専門家に質問してみよう