title: c: strategies for debugging obscure memory leaks?
body: <p>I'm working on a project in c, and I'm trying to understand how to debug an obscure bug that crashes my program. Its kinda large, attempts to isolate the problem by making smaller versions of the code are not working. So I'm trying to come up with a way to debug and pinpoint a memory leak.</p>
  
  <p>I came up with the following plan: I know the problem comes from running a certain function, and that function calls itself recursively. So I thought I could make a snapshot of sorts of my program memory allocation. Since I don't know jack about what happens under the hood (I know a little not enough to be useful in this situation):</p>
  
  <pre><code>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-&gt;num_allocs=1;
      nnew-&gt;num_frees=0;
      nnew-&gt;size_space=sizeof(RECORD);
      nnew-&gt;num_structure_1=0;
      ...
      nnew-&gt;num_structure_N=0;
      nnew-&gt;num_records=1;
      nnew-&gt;next=0;
      if(*top)
      {
          nnew-&gt;num_allocs+=(*top)-&gt;num_allocs;
          nnew-&gt;num_frees=(*top)-&gt;num_frees;
          nnew-&gt;size_space+=(*top)-&gt;size_space;
              nnew-&gt;num_structure_1=(*top)-&gt;num_allocs;
              ...
              nnew-&gt;num_structure_N=(*top)-&gt;num_allocs;
              nnew-&gt;num_records+=(*top)-&gt;num_records;
          nnew-&gt;next=*top;
      }
      *top=nnew;
  }
  </code></pre>
  
  <p>the idea being I print out the contents of my memory record keeping right before the moment my program crashes (I know where it crashes thanks to GDB).</p>
  
  <p>and then throughout the program (for each data structure in my program I have a similar push function like above) I can simply add a one liner with a function tallying datastructure allocations plus total stack (heap?) memory allocations (that I can keep track of). I simply make more memory_record structures wherever I feel the need to record a snapshot of my program running. Problem is this memory balance sheet recording won't helping if I can't somehow record how much memory is actually being used.</p>
  
  <p>But how would I do this? Plus how would I take dangling pointers and leaks into account? I'm using OS X and I'm currently looking up how I could record the stack pointer and other things.</p>
  
  <p>EDIT: Since you asked: output of valgrind: (closure() is the function called from main that returns the bad pointer: Its supposed to return the head of a doubly linked-list, traversehashmap() is a function called from closure() I use to calculate and append extra node to the linked-list and which calls itself recursively because it needs to jump around between nodes.)</p>
  
  <pre><code>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)
  </code></pre>