sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 1 | #include <stdio.h> |
| 2 | #include <stdlib.h> |
njn | c0b2618 | 2009-03-12 03:00:05 +0000 | [diff] [blame] | 3 | #include "leak.h" |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 4 | #include "../memcheck.h" |
| 5 | |
njn | c0b2618 | 2009-03-12 03:00:05 +0000 | [diff] [blame] | 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 | */ |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 16 | |
njn | c0b2618 | 2009-03-12 03:00:05 +0000 | [diff] [blame] | 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 | |
| 26 | Node* mk(void) |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 27 | { |
njn | c0b2618 | 2009-03-12 03:00:05 +0000 | [diff] [blame] | 28 | Node *x = malloc(sizeof(Node)); |
| 29 | x->l = NULL; |
| 30 | x->r = NULL; |
| 31 | return x; |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 32 | } |
| 33 | |
njn | c0b2618 | 2009-03-12 03:00:05 +0000 | [diff] [blame] | 34 | // This is a definite root. |
| 35 | Node* t; |
| 36 | |
| 37 | void f(void) |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 38 | { |
njn | c0b2618 | 2009-03-12 03:00:05 +0000 | [diff] [blame] | 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 |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 48 | |
njn | c0b2618 | 2009-03-12 03:00:05 +0000 | [diff] [blame] | 49 | // Sever B->D, leaking D |
| 50 | t->l->l = NULL; |
| 51 | |
| 52 | // Sever A->C, leaking C-F-G |
| 53 | t->r = NULL; |
sewardj | cbdddcf | 2005-03-10 23:23:45 +0000 | [diff] [blame] | 54 | } |
njn | c0b2618 | 2009-03-12 03:00:05 +0000 | [diff] [blame] | 55 | |
| 56 | int 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 | |
Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 65 | CLEAR_CALLER_SAVED_REGS; |
njn | c0b2618 | 2009-03-12 03:00:05 +0000 | [diff] [blame] | 66 | GET_FINAL_LEAK_COUNTS; |
| 67 | |
| 68 | PRINT_LEAK_COUNTS(stderr); |
| 69 | |
| 70 | return 0; |
| 71 | } |
| 72 | |