Home | History | Annotate | Download | only in tests
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include "leak.h"
      4 #include "../memcheck.h"
      5 
      6 // Pointer chain          AAA Category/output BBB Category/output
      7 // -------------          ------------------- ------------
      8 // p1 ---> AAA            DR / R
      9 // p2 ---> AAA ---> BBB   DR / R              IR / R
     10 // p3      AAA            DL / L
     11 // p4      AAA ---> BBB   DL / I              IL / L
     12 // p5 -?-> AAA            (y)DR, (n)DL / P
     13 // p6 ---> AAA -?-> BBB   DR / R              (y)IR, (n)DL / P
     14 // p7 -?-> AAA ---> BBB   (y)DR, (n)DL / P    (y)IR, (n)IL / P
     15 // p8 -?-> AAA -?-> BBB   (y)DR, (n)DL / P    (y,y)IR, (n,y)IL, (_,n)DL / P
     16 // p9      AAA -?-> BBB   DL / L              (y)IL, (n)DL / I
     17 //
     18 // Pointer chain legend:
     19 // - pN: a root set pointer
     20 // - AAA, BBB: heap blocks
     21 // - --->: a start-pointer
     22 // - -?->: an interior-pointer
     23 //
     24 // Category legend:
     25 // - DR: Directly reachable
     26 // - IR: Indirectly reachable
     27 // - DL: Directly lost
     28 // - IL: Indirectly lost
     29 // - (y)XY: it's XY if the interior-pointer is a real pointer
     30 // - (n)XY: it's XY if the interior-pointer is not a real pointer
     31 // - (_)XY: it's XY in either case
     32 //
     33 // How we handle the 9 cases:
     34 // - "directly lost":    case 3
     35 // - "indirectly lost":  cases 4, 9
     36 // - "possibly lost":    cases 5..8
     37 // - "still reachable":  cases 1, 2
     38 
     39 
     40 typedef
     41    struct _Node {
     42       struct _Node* next;
     43       // Padding ensures the structu is the same size on 32-bit and 64-bit
     44       // machines.
     45       char padding[8 - sizeof(struct _Node*)];
     46    } Node;
     47 
     48 Node* mk(Node* next)
     49 {
     50    // We allocate two nodes, so we can do p+1 and still point within the
     51    // block.
     52    Node* x = malloc(2 * sizeof(Node));
     53    x->next = next;
     54    return x;
     55 }
     56 
     57 // These are definite roots.
     58 Node* p1;
     59 Node* p2;
     60 Node* p3;
     61 Node* p4;
     62 Node* p5;
     63 Node* p6;
     64 Node* p7;
     65 Node* p8;
     66 Node* p9;
     67 
     68 void f(void)
     69 {
     70    p1 = mk(NULL);       // Case 1: 16/1 still reachable
     71 
     72    p2 = mk(mk(NULL));   // Case 2: 16/1 still reachable
     73                                 // 16/1 still reachable
     74    (void)mk(NULL);      // Case 3: 16/1 definitely lost
     75 
     76    (void)mk(mk(NULL));  // Case 4: 16/1 indirectly lost (counted again below!)
     77                                 // 32(16d,16i)/1 definitely lost (double count!)
     78    p5 = mk(NULL);       // Case 5: 16/1 possibly lost (ok)
     79    p5++;
     80 
     81    p6 = mk(mk(NULL));   // Case 6: 16/1 still reachable
     82    (p6->next)++;                // 16/1 possibly lost
     83 
     84    p7 = mk(mk(NULL));   // Case 7: 16/1 possibly lost
     85    p7++;                        // 16/1 possibly lost
     86 
     87    p8 = mk(mk(NULL));   // Case 8: 16/1 possibly lost
     88    (p8->next)++;                // 16/1 possibly lost
     89    p8++;
     90 
     91    p9 = mk(mk(NULL));   // Case 9: 16/1 indirectly lost (counted again below!)
     92    (p9->next)++;                // 32(16d,16i)/1 definitely lost (double count!)
     93    p9 = NULL;
     94 }
     95 
     96 int main(void)
     97 {
     98    DECLARE_LEAK_COUNTERS;
     99 
    100    GET_INITIAL_LEAK_COUNTS;
    101 
    102    // Originally, this program did all the work in main(), but on some
    103    // platforms (x86/Darwin and AMD64/Linux with --enable-only32bit) stray
    104    // pointers to supposedly-lost heap blocks were being left on the stack,
    105    // thus making them reachable.  Doing the allocations in f() and the leak
    106    // counting in main() avoids the problem.
    107    f();
    108 
    109    CLEAR_CALLER_SAVED_REGS;
    110    GET_FINAL_LEAK_COUNTS;
    111 
    112    PRINT_LEAK_COUNTS(stderr);
    113 
    114    return 0;
    115 }
    116