mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-10 09:26:15 +00:00
72 lines
1.3 KiB
C
72 lines
1.3 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "leak.h"
|
|
#include "../memcheck.h"
|
|
|
|
/* We build this tree:
|
|
|
|
A
|
|
/ \
|
|
B C
|
|
/ \ / \
|
|
D E F G
|
|
|
|
Then we leak D and C-F-G.
|
|
*/
|
|
|
|
typedef
|
|
struct _Node {
|
|
struct _Node *l;
|
|
struct _Node *r;
|
|
// Padding ensures the structu is the same size on 32-bit and 64-bit
|
|
// machines.
|
|
char padding[16 - 2*sizeof(struct _Node*)];
|
|
} Node;
|
|
|
|
Node* mk(void)
|
|
{
|
|
Node *x = malloc(sizeof(Node));
|
|
x->l = NULL;
|
|
x->r = NULL;
|
|
return x;
|
|
}
|
|
|
|
// This is a definite root.
|
|
Node* t;
|
|
|
|
void f(void)
|
|
{
|
|
// Building like this rather than "t = mk(mk(mk(NULL, NULL), ...)" seems to
|
|
// help avoid leaving pointers on the stack to supposedly-leaked blocks.
|
|
t = mk(); // A
|
|
t->l = mk(); // B
|
|
t->r = mk(); // C (48(16d,32i)/1 definitely leaked from here)
|
|
t->l->l = mk(); // D (16/1 definitely leaked from here)
|
|
t->l->r = mk(); // E
|
|
t->r->l = mk(); // F
|
|
t->r->r = mk(); // G
|
|
|
|
// Sever B->D, leaking D
|
|
t->l->l = NULL;
|
|
|
|
// Sever A->C, leaking C-F-G
|
|
t->r = NULL;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
DECLARE_LEAK_COUNTERS;
|
|
|
|
GET_INITIAL_LEAK_COUNTS;
|
|
|
|
// See leak-cases.c for why we do the work in f().
|
|
f();
|
|
|
|
GET_FINAL_LEAK_COUNTS;
|
|
|
|
PRINT_LEAK_COUNTS(stderr);
|
|
|
|
return 0;
|
|
}
|
|
|