私は C でプロジェクトに取り組んでおり、プログラムをクラッシュさせるあいまいなバグをデバッグする方法を理解しようとしています。コードの小さなバージョンを作成して問題を切り分けようとする試みは、かなり大規模であり、機能していません。だから私は、メモリリークをデバッグして特定する方法を考え出そうとしています。
私は次の計画を思いつきました: 問題が特定の関数の実行に起因することはわかっており、その関数はそれ自体を再帰的に呼び出します。そこで、プログラムのメモリ割り当てのスナップショットを作成できると考えました。ボンネットの下で何が起こっているかについてジャックを知らないので(この状況で役立つには少し足りないことを知っています):
typedef struct record_mem {
int num_allocs;
int num_frees;
int size_space;
int num_structure_1;
...
int num_structure_N;
int num_records;
struct record_mem *next;
} RECORD;
extern RECORD *top;
void pushmem(RECORD **top)
{
RECORD *nnew = 0;
RECORD *nnew = (RECORD *)malloc(sizeof(RECORD));
nnew->num_allocs=1;
nnew->num_frees=0;
nnew->size_space=sizeof(RECORD);
nnew->num_structure_1=0;
...
nnew->num_structure_N=0;
nnew->num_records=1;
nnew->next=0;
if(*top)
{
nnew->num_allocs+=(*top)->num_allocs;
nnew->num_frees=(*top)->num_frees;
nnew->size_space+=(*top)->size_space;
nnew->num_structure_1=(*top)->num_allocs;
...
nnew->num_structure_N=(*top)->num_allocs;
nnew->num_records+=(*top)->num_records;
nnew->next=*top;
}
*top=nnew;
}
プログラムがクラッシュする瞬間の直前に保持しているメモリレコードの内容を印刷するという考えです(GDBのおかげでクラッシュする場所を知っています)。
そして、プログラム全体で(プログラムの各データ構造に対して、上記のような同様のプッシュ関数があります)、データ構造の割り当てと合計スタック(ヒープ?)のメモリ割り当てを集計する関数を含む1つのライナーを追加するだけです(追跡できます)の)。私は、実行中のプログラムのスナップショットを記録する必要があると感じた場所に、さらに memory_record 構造を作成するだけです。問題は、実際に使用されているメモリの量を何らかの方法で記録できない場合、このメモリバランスシートの記録が役に立たないことです。
しかし、どうすればこれを行うことができますか?さらに、ぶら下がっているポインターとリークをどのように考慮に入れるでしょうか? 私はOS Xを使用していますが、スタックポインタなどを記録する方法を現在調べています。
編集: あなたが尋ねたので: valgrind の出力: (closure() は、悪いポインターを返す main から呼び出される関数です: 二重リンクリストの先頭を返すはずです。私は余分なノードを計算してリンクリストに追加し、ノード間をジャンプする必要があるため、それ自体を再帰的に呼び出します。)
jason-danckss-macbook:project Jason$ valgrind --leak-check=full --tool=memcheck ./testc
Will attempt to compute closure of AB:
Result: testcl: 0x10000d0b0
==7682== Invalid read of size 8
==7682== at 0x100001D4E: printrelation2 (relation.h:490)
==7682== by 0x100003CFE: main (test-computation.c:47)
==7682== Address 0x10000cee8 is 8 bytes inside a block of size 24 free'd
==7682== at 0xD828: free (vg_replace_malloc.c:450)
==7682== by 0x100001232: destroyrelation2 (relation.h:161)
==7682== by 0x100003407: destroyallhashmap (computation.h:333)
==7682== by 0x1000039E1: closure (computation.h:539)
==7682== by 0x100003CBE: main (test-computation.c:38)
==7682==
==7682==
==7682== HEAP SUMMARY:
==7682== in use at exit: 5,360 bytes in 48 blocks
==7682== total heap usage: 99 allocs, 51 frees, 6,640 bytes allocated
==7682==
==7682== 48 (24 direct, 24 indirect) bytes in 1 blocks are definitely lost in loss record 33 of 37
==7682== at 0xC283: malloc (vg_replace_malloc.c:274)
==7682== by 0x100001104: getnewrelation (relation.h:134)
==7682== by 0x100001848: copyrelation (relation.h:343)
==7682== by 0x100003991: closure (computation.h:531)
==7682== by 0x100003CBE: main (test-computation.c:38)
==7682==
==7682== 1,128 (24 direct, 1,104 indirect) bytes in 1 blocks are definitely lost in loss record 36 of 37
==7682== at 0xC283: malloc (vg_replace_malloc.c:274)
==7682== by 0x100002315: getnewholder (dependency.h:129)
==7682== by 0x100003B17: main (test-computation.c:14)
==7682==
==7682== LEAK SUMMARY:
==7682== definitely lost: 48 bytes in 2 blocks
==7682== indirectly lost: 1,128 bytes in 44 blocks
==7682== possibly lost: 0 bytes in 0 blocks
==7682== still reachable: 4,096 bytes in 1 blocks
==7682== suppressed: 88 bytes in 1 blocks
==7682== Reachable blocks (those to which a pointer was found) are not shown.
==7682== To see them, rerun with: --leak-check=full --show-reachable=yes
==7682==
==7682== For counts of detected and suppressed errors, rerun with: -v
==7682== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)