1 #include <stdio.h> 2 #include <stdlib.h> 3 #include "leak.h" 4 #include "../memcheck.h" 5 6 /* We build this tree: 7 8 A 9 / \ 10 B C 11 / \ / \ 12 D E F G 13 14 Then we leak D and C-F-G. 15 */ 16 17 typedef 18 struct _Node { 19 struct _Node *l; 20 struct _Node *r; 21 // Padding ensures the structu is the same size on 32-bit and 64-bit 22 // machines. 23 char padding[16 - 2*sizeof(struct _Node*)]; 24 } Node; 25 mk(void)26Node* mk(void) 27 { 28 Node *x = malloc(sizeof(Node)); 29 x->l = NULL; 30 x->r = NULL; 31 return x; 32 } 33 34 // This is a definite root. 35 Node* t; 36 f(void)37void f(void) 38 { 39 // Building like this rather than "t = mk(mk(mk(NULL, NULL), ...)" seems to 40 // help avoid leaving pointers on the stack to supposedly-leaked blocks. 41 t = mk(); // A 42 t->l = mk(); // B 43 t->r = mk(); // C (48(16d,32i)/1 definitely leaked from here) 44 t->l->l = mk(); // D (16/1 definitely leaked from here) 45 t->l->r = mk(); // E 46 t->r->l = mk(); // F 47 t->r->r = mk(); // G 48 49 // Sever B->D, leaking D 50 t->l->l = NULL; 51 52 // Sever A->C, leaking C-F-G 53 t->r = NULL; 54 } 55 main(void)56int main(void) 57 { 58 DECLARE_LEAK_COUNTERS; 59 60 GET_INITIAL_LEAK_COUNTS; 61 62 // See leak-cases.c for why we do the work in f(). 63 f(); 64 65 GET_FINAL_LEAK_COUNTS; 66 67 PRINT_LEAK_COUNTS(stderr); 68 69 return 0; 70 } 71 72