• ベストアンサー

C言語のメモリリークに関して

malloc()、calloc()等で確保した回数とそれをfreeした回数が等しければ、メモリリークが起きていないことを保障できますか? 回数が等しくてメモリリークが起きているとすればどんな原因が考えられるでしょうか?

noname#69066
noname#69066

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

  • ベストアンサー
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.5

>   ・保存しておいたポインタと引数で渡されたポインタが等しい場合はカウンタ変数をデクリメント a = malloc(10); ... free(a); b = malloc(1000); ... free(b); という風に、malloc()とfree()がクロスしていない場合はOKでありましょう。 下記のような現象が起きているのではありませんか? a = malloc(10); ... b = malloc(1000); ... free(a); /* ここで、aとbとが異なるため、freeの回数をデクリメントしない */ ... free(b);

noname#69066
質問者

お礼

ありがとうございます。 言葉足らずで申し訳ありません。 正しく書きますと int count = 0; /* カウンタ変数 */ typedef struct _mem_info {  unsigned int address;  int size; } mem_info; mem_info mem [10000]; /* メモリ情報保存用 */ などとして、カウンタ変数とメモリ情報保存用のものは別々にしています。 そしてalloc時は各カウンタごとにmem[count]に情報を保存しています。 free時は引数でptrが渡され、 for (int i=0; i<count; i++) {  if (mem[i].address == (unsigned int)ptr) {    count--;    break;  } } などとしており、この時最終的にカウンタは0にならず、if文とfor文がなければカウンタは0になります。

noname#69066
質問者

補足

回答へのお礼で間違いがありました。 free時は for (int i=0; i<count; i++) {  if (mem[i].address == (unsigned int)ptr) {    for (int j=i; j<count; j++ ) {     mem[j] = mem[j+1];    }    count--;    break;  } } 上記のようにif文で一致した場合はcountの削減と同時にmem[]の内容も更新しております。 大変失礼いたしました。

その他の回答 (4)

  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.4

Ano.1です. 俗にmallocデバッガなどとよばれるmalloc/freeの失敗をしらべるためのツールがありますからそれを使ってみるのも1つの手段です. とはいえ,「reeの際は実際に開放したサイズはわからないですよね?」などと書いておられることから,malloc/freeについて本当に理解しておられるのか心配です.freeはmallocしたサイズを開放します.1回のmallocで得た領域を複数回に分けて開放するなんてことは出来ないです. あと,そもそもどういう根拠でメモリリークしていると判断されたのでしょうか?

noname#69066
質問者

お礼

再度ありがとうございます。 判断した根拠は、グローバルでカウンタ変数とメモリ領域へのポインタを格納する構造体を定義して 1)alloc時   ・malloc、calloc、strdup時はカウンタ変数をインクリメントして戻り値のポインタを保存   ・realloc時は保存していたポインタを新しいものに更新してカウントはそのまま 2)free時   ・保存しておいたポインタと引数で渡されたポインタが等しい場合はカウンタ変数をデクリメント として処理を実行すると、本来はすべて開放しきってるはずなのにカウンタ変数が0にならないのです。 また、free時の条件文をなくし、単にfreeが呼び出された回数だけデクリメントするとカウンタ変数が0になります。 これより、正しくない領域をfreeして、実際に開放していない部分が残ってるのではと思いました。 もしかすると確認用のコードもまずいところがあるかもしれません。。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

> malloc()、calloc()等で確保した回数とそれをfreeした回数が等しければ、メモリリークが起きていないことを保障できますか? 保障できません。 標準関数の範囲でも、mallocとcalloc以外でメモリブロックを動的に割付ける関数がいくつかあります。例えば、reallocとかsetvbufとかです。 非標準関数まで含めれば、strdupなどの分かりやすいものをはじめ、さまざまな可能性が考えられますし、mallocとは別の機構による動的割付けもあり得ます。

noname#69066
質問者

お礼

ありがとうございます。 確保する関数はmallocとcallocとreallocとstrdupのみ使用しています

  • Tasuke22
  • ベストアンサー率33% (1799/5383)
回答No.2

保障も何もならないでしょう。 malloc()、calloc()などがなくとも、メモリリークは 発生します。 少なくとも、これさえしていたら保障になるという捉 え方は捨てた方が賢明と思えます。 何をやっても保障にならないからテストをキチンとし 精度アップを計ります。 原因としては多々ありますが、配列のサイズを超えて ポイントが入っている場所を壊し、そのポインタを使 えば簡単に発生します。その他、色々なパターンや 複合した複雑なパターンなど想像を絶するのも多々あ るでしょう。

noname#69066
質問者

お礼

ありがとうございます。 複雑なパターンだとデバッグがしにくそうですね・・ malloc、calloc、realloc等では確保するサイズを指定しますが、freeの際は実際に開放したサイズはわからないですよね? それが分かればデバッグもし易そうなのですが。。。

  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.1

・同じメモリエリアを複数回freeしている。 ・malloc/callocで得られたのではないアドレスをfreeに渡している ・mallocの管理メモリ領域を壊したため、malloc/freeが正しく動かなくなっている  (malloc(10)で得たエリアに20バイトのデータを置くとかすると、管理領域が壊れることがあります)

noname#69066
質問者

お礼

ありがとうございます。 回答いただいた点を考慮しながらもう一度見直してみます。 申し送れましたが、質問の動機は、 今自分が作ってるコードでどうやらメモリリークが起きているようなのですが、その場所がわからずに困っているという状況だからです。 メモリの確保と開放を呼び出している回数をチェックすると等しいのですが、 アドレスが異なっているのか、メモリ領域を壊したのか、すべて開放しきれていないようで悩んでいます

関連するQ&A

  • c言語のメモリリークについての質問

    c言語のメモリリークについての質問 c言語初心者のため、メモリリークについて質問させていただければと存じます。 下記のコードで、 char* char_p = "char1"; char_p = "char2"; // ←メモリリーク? 2行目の部分は、 "char1"のメモリ領域が確保されたままで、解放できなくなってしまうので、 メモリリークを起こして問題な気がするのですが、実際はどうなのでしょうか? よろしくお願いいたします。

  • C/C++言語のメモリについて

    C言語でメモリを2種類?に分けると、スタックとヒープがあります。 ヒープは mallocなどで確保し、freeで解放しますがスタックは解放する必要がありません。 そのスタックは通常、何バイトまで可能なのでしょうか? あと関数外のファイルの先頭に int[1000000];とした場合、このメモリはmallocで確保していませんが、 どこに作られるのでしょうか? 私のパソコンはメモリが2GBでWindows2000ですが、CやC++で最大、何バイトまでメモリが使えますか? また、一番多くメモリを確保できるなら、OSはなんでも構いません。 解釈等も間違っていたらご指摘していただきたいです。

  • メモリリークについて

    VC6.0でデバッグ実行すると Detected memory leaks! Dumping objects -> ソースファイル名(932) : {136739} normal block at 0x00FD4AC0, 0 bytes long. Data: <> メッセージがあり メモリがリークしているようです メッセージやソースから察するに 0バイトの領域を確保し それを解放したときに起こっているようです 領域をmallocして 解放ではNULLでなければ解放 という処理はしてはいけないことなのでしょうか 0バイトの領域を確保した場合 又は0バイトの領域を確保しないように 処理しないといけないのでしょうか? 知識のある方よろしくお願い致します

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

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

  • メモリリークを調べています。

    メモリリークを調べています。 MFC(VC2005)です。 MFC拡張DLLで作成したアプリケーションにメモリリークがないかを調査し始めたのですが、VisualStudioでデバッグでは 「Detected memory leaks!」は出ません。 パフォーマンスモニタで、このDLLを静的リンクしたEXEのPrivateByteを約90時間監視すると、2回だけ大きな上昇(といっても数10KB)が見られました。 上昇するまでは横ばいですが、この横ばいの時間が2回とも異なります。 これはメモリリークと言えるのでしょうか? ちなみに、このDLLの調査対象機能は画像描画機能で、定期的にメモリ確保→メモリ解放を繰り返します。 メモリリークでないとしたら、どう結論付けたら良いでしょうか? 解決方法はありますか? 私としてはフラグメンテーションを疑っています。

  • 動的メモリとexit(C言語)

    fpA=fopen("name1", "r"); fpB=fopen("name2", "r"); fpC=fopen("name3", "r"); if(fpA==NULL || fpB==NULL || fpC==NULL){ exit(1); } fpAとfpBのファイルオープンに成功してfpCで失敗した場合、exit(1)によってfpAとfpBはクローズされますよね? じゃあ、 a=malloc(size); b=malloc(size); c=malloc(size); if(a==NULL || b==NULL || c==NULL){ exit(1); } aとbのメモリ確保に成功してcで失敗した場合、aとbのメモリはどうなっちゃうんでしょう?exitは動的メモリも解放してくれるのですか? とりあえず以下のようにしてますが…。 a=malloc(size); b=malloc(size); c=malloc(size); if(a==NULL || b==NULL || c==NULL){ free(a); free(b); free(c); exit(1); }

  • C言語のプログラムのメモリリークに関して

    動的メモリ管理を用いて,キーボードからの入力を行単位で辞書順にソートして出力するプログラムで、メモリリークが有るため解消したいのですが、freeをどのように用いれば良いのかが分かりません。 動的メモリについての理解が不十分であるため、自分なりにfreeを用いてみるとプログラムが途中で止まってしまい、解消することができません。 以下のプログラムは、自分なりにfreeを用いた部分を除けば、ソート後の出力は正しく出力されます。(メモリリークは発生します。) アドバイス、間違いの指摘等していただければと思います。お願いします。 環境は、Windows XP Professional SP3 32bitでVisual C++ 2008 Expressを使用しています。 #include <stdio.h> #include <string.h> #include <crtdbg.h> #include <stdlib.h> #define MAXLINES 20000 // 最大行数 #define LINELENGTH 20 // 1行の最大文字数 /* 標準入力からの入力を,一行づつ動的に確保したメモリに格納し, そのアドレスを文字列へのポインタ配列に保存する. Ctrl+Zで入力を終了する. lines : 文字列へのポインタの配列 numMax : 最大の読み込み行数*/ int ReadLines(char *lines[], int numMax){ int cnt = 0; static char buf[LINELENGTH]; while (cnt < numMax && gets(buf)) { lines[cnt] = malloc(strlen(buf) + 1); if (lines[cnt] == NULL) { printf("Allocation error.\n"); break; } strcpy(lines[cnt], buf); cnt++; } return cnt; } /* ポインタ配列の指す文字列を標準出力に表示 lines : 文字列へのポインタの配列 num : 行数*/ void PrintLines(char *lines[], int num){ int i; for (i = 0;i < num;i++) printf("%s\n", lines[i]); } /* ポインタの配列を,辞書順にソート lines : 文字列へのポインタの配列 num : 行数*/ void Sort(char *lines[], int num){ int i,j; char temp[LINELENGTH]; for(i=0;i<num;i++){ for(j=num-1;j>i;j--){ if(strcmp(lines[j],lines[j-1])<0){ strcpy(temp,lines[j]); strcpy(lines[j],lines[j-1]); strcpy(lines[j-1],temp); } } } } int main(){ int cnt,i; static char *lines[MAXLINES]; cnt = ReadLines(lines, MAXLINES); printf("----- %d lines -----\n", cnt); Sort(lines, cnt); PrintLines(lines, cnt); /*自分なりにfreeを用いた部分*/ for(i=0;i<cnt;i++){ free(lines[i]); } //メモリリーク情報の表示 _CrtDumpMemoryLeaks(); return 0; }

  • C言語 mallocとfreeについて

    mallocとfreeを何度も繰り返していると、メモリがどんどん増えていき、最終的にはプログラムが止まってしまいます。 いくつかのページでメモリ確保を繰り返すとメモリをかなり食ってしまうと書いてありました。 これに対する解決策をご存知の方いらっしゃいましたら教えてください。 よろしくお願いします。

  • Delphiでのメモリリーク検出

    Delphi6Proを使用しています。 Delphi自体にはメモリリークを検出する仕組みはないのでしょうか? またメモリリーク検出に使えるソフトウェアってありますか? フリーでも商用でも結構ですので教えて下さい。

  • C言語 動的なメモリの確保 実行できない

    malloc関数を使いメモリを確保しそこへ"ABCD"と記憶させ、ポインタ*Cを使い確保したメモリの内容を表示するプログラムです。 ********************************************* #include <stdio.h> #include <stdlib.h> int main(void) {   int i;   char *C;   C = (char *) malloc (sizeof(char) * 5);   C = "ABCD";   for(i = 0; i < 5; i++){     if(C[i] != NULL){       printf("%s", C[i]);    ←※エラー※     }   }   free(C);   return 0; } ********************************************* 正常にコンパイルできますが実行エラーになります。VCを使いF10のデバッグテストで※のところエラーになります。なぜなのでしょうか?

専門家に質問してみよう