18225cc0de2ccf390127b5910dceb7c6185091a38njn#include <stdio.h> 28225cc0de2ccf390127b5910dceb7c6185091a38njn#include <stdlib.h> 38225cc0de2ccf390127b5910dceb7c6185091a38njn#include "leak.h" 48225cc0de2ccf390127b5910dceb7c6185091a38njn#include "../memcheck.h" 58225cc0de2ccf390127b5910dceb7c6185091a38njn 68225cc0de2ccf390127b5910dceb7c6185091a38njn// Pointer chain AAA Category/output BBB Category/output 78225cc0de2ccf390127b5910dceb7c6185091a38njn// ------------- ------------------- ------------ 88225cc0de2ccf390127b5910dceb7c6185091a38njn// p1 ---> AAA DR / R 98225cc0de2ccf390127b5910dceb7c6185091a38njn// p2 ---> AAA ---> BBB DR / R IR / R 108225cc0de2ccf390127b5910dceb7c6185091a38njn// p3 AAA DL / L 118225cc0de2ccf390127b5910dceb7c6185091a38njn// p4 AAA ---> BBB DL / I IL / L 128225cc0de2ccf390127b5910dceb7c6185091a38njn// p5 -?-> AAA (y)DR, (n)DL / P 138225cc0de2ccf390127b5910dceb7c6185091a38njn// p6 ---> AAA -?-> BBB DR / R (y)IR, (n)DL / P 148225cc0de2ccf390127b5910dceb7c6185091a38njn// p7 -?-> AAA ---> BBB (y)DR, (n)DL / P (y)IR, (n)IL / P 158225cc0de2ccf390127b5910dceb7c6185091a38njn// p8 -?-> AAA -?-> BBB (y)DR, (n)DL / P (y,y)IR, (n,y)IL, (_,n)DL / P 168225cc0de2ccf390127b5910dceb7c6185091a38njn// p9 AAA -?-> BBB DL / L (y)IL, (n)DL / I 178225cc0de2ccf390127b5910dceb7c6185091a38njn// 188225cc0de2ccf390127b5910dceb7c6185091a38njn// Pointer chain legend: 198225cc0de2ccf390127b5910dceb7c6185091a38njn// - pN: a root set pointer 208225cc0de2ccf390127b5910dceb7c6185091a38njn// - AAA, BBB: heap blocks 218225cc0de2ccf390127b5910dceb7c6185091a38njn// - --->: a start-pointer 228225cc0de2ccf390127b5910dceb7c6185091a38njn// - -?->: an interior-pointer 238225cc0de2ccf390127b5910dceb7c6185091a38njn// 248225cc0de2ccf390127b5910dceb7c6185091a38njn// Category legend: 258225cc0de2ccf390127b5910dceb7c6185091a38njn// - DR: Directly reachable 268225cc0de2ccf390127b5910dceb7c6185091a38njn// - IR: Indirectly reachable 278225cc0de2ccf390127b5910dceb7c6185091a38njn// - DL: Directly lost 288225cc0de2ccf390127b5910dceb7c6185091a38njn// - IL: Indirectly lost 298225cc0de2ccf390127b5910dceb7c6185091a38njn// - (y)XY: it's XY if the interior-pointer is a real pointer 308225cc0de2ccf390127b5910dceb7c6185091a38njn// - (n)XY: it's XY if the interior-pointer is not a real pointer 318225cc0de2ccf390127b5910dceb7c6185091a38njn// - (_)XY: it's XY in either case 328225cc0de2ccf390127b5910dceb7c6185091a38njn// 338225cc0de2ccf390127b5910dceb7c6185091a38njn// How we handle the 9 cases: 348225cc0de2ccf390127b5910dceb7c6185091a38njn// - "directly lost": case 3 358225cc0de2ccf390127b5910dceb7c6185091a38njn// - "indirectly lost": cases 4, 9 368225cc0de2ccf390127b5910dceb7c6185091a38njn// - "possibly lost": cases 5..8 378225cc0de2ccf390127b5910dceb7c6185091a38njn// - "still reachable": cases 1, 2 388225cc0de2ccf390127b5910dceb7c6185091a38njn 398225cc0de2ccf390127b5910dceb7c6185091a38njn 408225cc0de2ccf390127b5910dceb7c6185091a38njntypedef 418225cc0de2ccf390127b5910dceb7c6185091a38njn struct _Node { 428225cc0de2ccf390127b5910dceb7c6185091a38njn struct _Node* next; 438225cc0de2ccf390127b5910dceb7c6185091a38njn // Padding ensures the structu is the same size on 32-bit and 64-bit 448225cc0de2ccf390127b5910dceb7c6185091a38njn // machines. 458225cc0de2ccf390127b5910dceb7c6185091a38njn char padding[8 - sizeof(struct _Node*)]; 468225cc0de2ccf390127b5910dceb7c6185091a38njn } Node; 478225cc0de2ccf390127b5910dceb7c6185091a38njn 488225cc0de2ccf390127b5910dceb7c6185091a38njnNode* mk(Node* next) 498225cc0de2ccf390127b5910dceb7c6185091a38njn{ 508225cc0de2ccf390127b5910dceb7c6185091a38njn // We allocate two nodes, so we can do p+1 and still point within the 518225cc0de2ccf390127b5910dceb7c6185091a38njn // block. 528225cc0de2ccf390127b5910dceb7c6185091a38njn Node* x = malloc(2 * sizeof(Node)); 538225cc0de2ccf390127b5910dceb7c6185091a38njn x->next = next; 548225cc0de2ccf390127b5910dceb7c6185091a38njn return x; 558225cc0de2ccf390127b5910dceb7c6185091a38njn} 568225cc0de2ccf390127b5910dceb7c6185091a38njn 578225cc0de2ccf390127b5910dceb7c6185091a38njn// These are definite roots. 588225cc0de2ccf390127b5910dceb7c6185091a38njnNode* p1; 598225cc0de2ccf390127b5910dceb7c6185091a38njnNode* p2; 608225cc0de2ccf390127b5910dceb7c6185091a38njnNode* p3; 618225cc0de2ccf390127b5910dceb7c6185091a38njnNode* p4; 628225cc0de2ccf390127b5910dceb7c6185091a38njnNode* p5; 638225cc0de2ccf390127b5910dceb7c6185091a38njnNode* p6; 648225cc0de2ccf390127b5910dceb7c6185091a38njnNode* p7; 658225cc0de2ccf390127b5910dceb7c6185091a38njnNode* p8; 668225cc0de2ccf390127b5910dceb7c6185091a38njnNode* p9; 678225cc0de2ccf390127b5910dceb7c6185091a38njn 68402c1a1c1dd72673a2adcfd5bded97180507a727njnvoid f(void) 698225cc0de2ccf390127b5910dceb7c6185091a38njn{ 708225cc0de2ccf390127b5910dceb7c6185091a38njn p1 = mk(NULL); // Case 1: 16/1 still reachable 718225cc0de2ccf390127b5910dceb7c6185091a38njn 728225cc0de2ccf390127b5910dceb7c6185091a38njn p2 = mk(mk(NULL)); // Case 2: 16/1 still reachable 738225cc0de2ccf390127b5910dceb7c6185091a38njn // 16/1 still reachable 748225cc0de2ccf390127b5910dceb7c6185091a38njn (void)mk(NULL); // Case 3: 16/1 definitely lost 758225cc0de2ccf390127b5910dceb7c6185091a38njn 768225cc0de2ccf390127b5910dceb7c6185091a38njn (void)mk(mk(NULL)); // Case 4: 16/1 indirectly lost (counted again below!) 778225cc0de2ccf390127b5910dceb7c6185091a38njn // 32(16d,16i)/1 definitely lost (double count!) 788225cc0de2ccf390127b5910dceb7c6185091a38njn p5 = mk(NULL); // Case 5: 16/1 possibly lost (ok) 798225cc0de2ccf390127b5910dceb7c6185091a38njn p5++; 808225cc0de2ccf390127b5910dceb7c6185091a38njn 818225cc0de2ccf390127b5910dceb7c6185091a38njn p6 = mk(mk(NULL)); // Case 6: 16/1 still reachable 828225cc0de2ccf390127b5910dceb7c6185091a38njn (p6->next)++; // 16/1 possibly lost 838225cc0de2ccf390127b5910dceb7c6185091a38njn 848225cc0de2ccf390127b5910dceb7c6185091a38njn p7 = mk(mk(NULL)); // Case 7: 16/1 possibly lost 858225cc0de2ccf390127b5910dceb7c6185091a38njn p7++; // 16/1 possibly lost 868225cc0de2ccf390127b5910dceb7c6185091a38njn 878225cc0de2ccf390127b5910dceb7c6185091a38njn p8 = mk(mk(NULL)); // Case 8: 16/1 possibly lost 888225cc0de2ccf390127b5910dceb7c6185091a38njn (p8->next)++; // 16/1 possibly lost 898225cc0de2ccf390127b5910dceb7c6185091a38njn p8++; 908225cc0de2ccf390127b5910dceb7c6185091a38njn 918225cc0de2ccf390127b5910dceb7c6185091a38njn p9 = mk(mk(NULL)); // Case 9: 16/1 indirectly lost (counted again below!) 928225cc0de2ccf390127b5910dceb7c6185091a38njn (p9->next)++; // 32(16d,16i)/1 definitely lost (double count!) 938225cc0de2ccf390127b5910dceb7c6185091a38njn p9 = NULL; 94402c1a1c1dd72673a2adcfd5bded97180507a727njn} 95402c1a1c1dd72673a2adcfd5bded97180507a727njn 96402c1a1c1dd72673a2adcfd5bded97180507a727njnint main(void) 97402c1a1c1dd72673a2adcfd5bded97180507a727njn{ 98402c1a1c1dd72673a2adcfd5bded97180507a727njn DECLARE_LEAK_COUNTERS; 99402c1a1c1dd72673a2adcfd5bded97180507a727njn 100402c1a1c1dd72673a2adcfd5bded97180507a727njn GET_INITIAL_LEAK_COUNTS; 101402c1a1c1dd72673a2adcfd5bded97180507a727njn 102402c1a1c1dd72673a2adcfd5bded97180507a727njn // Originally, this program did all the work in main(), but on some 103402c1a1c1dd72673a2adcfd5bded97180507a727njn // platforms (x86/Darwin and AMD64/Linux with --enable-only32bit) stray 104402c1a1c1dd72673a2adcfd5bded97180507a727njn // pointers to supposedly-lost heap blocks were being left on the stack, 105402c1a1c1dd72673a2adcfd5bded97180507a727njn // thus making them reachable. Doing the allocations in f() and the leak 106402c1a1c1dd72673a2adcfd5bded97180507a727njn // counting in main() avoids the problem. 107402c1a1c1dd72673a2adcfd5bded97180507a727njn f(); 1088225cc0de2ccf390127b5910dceb7c6185091a38njn 109a5dda3e6bf767113c056a94e378417c8a1468dbbsewardj CLEAR_CALLER_SAVED_REGS; 1108225cc0de2ccf390127b5910dceb7c6185091a38njn GET_FINAL_LEAK_COUNTS; 1118225cc0de2ccf390127b5910dceb7c6185091a38njn 1128225cc0de2ccf390127b5910dceb7c6185091a38njn PRINT_LEAK_COUNTS(stderr); 1138225cc0de2ccf390127b5910dceb7c6185091a38njn 1148225cc0de2ccf390127b5910dceb7c6185091a38njn return 0; 1158225cc0de2ccf390127b5910dceb7c6185091a38njn} 116