Bringing apdf from vendor into main branch.
[AROS-Contrib.git] / apdf / goo / gdebug.cc
blob7d0952deb8000e0272824e837c34b2bb961fe545
1 //========================================================================
2 //
3 // gdebug.cc
4 //
5 // Copyright 2000-2001 Emmanuel Lesueur
6 //
7 //========================================================================
9 #ifdef DEBUG_MEM
11 #include "gdebug.h"
12 #include <stdio.h>
13 #include <string.h>
15 GDebug::Context *GDebug::Context::current;
17 struct GDebug::Tracker::Tracked {
18 void *object;
19 const char ** context;
22 struct GDebug::Tracker::TrackedArray {
23 TrackedArray() : array(NULL), size(0), max(0) {}
24 ~TrackedArray() {
25 for (int k = 0; k < size; ++k)
26 Context::free(array[k].context);
27 delete [] array;
29 Tracked *array;
30 int size;
31 int max;
34 GDebug::Tracker::Tracker() : tracked(new TrackedArray [size]) {
37 GDebug::Tracker::~Tracker() {
38 for (int i = 0; i < size; ++i) {
39 for (int k = 0; k < tracked[i].size; ++k) {
40 fprintf(stderr, "Object %lx not freed. Allocated at:\n", tracked[i].array[k].object);
41 Context::print(tracked[i].array[k].context);
42 fprintf(stderr, "\n");
43 show(tracked[i].array[k].object);
46 delete [] tracked;
49 void GDebug::Tracker::show(void*) {}
51 void GDebug::Tracker::track(void *object) {
52 int hash = ((unsigned)object >> 4) % size;
54 if (tracked[hash].size == tracked[hash].max) {
55 int sz = tracked[hash].size * 2 + 16;
56 Tracked *p = new Tracked[sz];
57 if (tracked[hash].size)
58 memcpy(p, tracked[hash].array, sizeof(*p) * tracked[hash].size);
59 delete [] tracked[hash].array;
60 tracked[hash].array = p;
61 tracked[hash].max = sz;
64 tracked[hash].array[tracked[hash].size].object = object;
65 tracked[hash].array[tracked[hash].size].context = Context::save();
66 ++tracked[hash].size;
69 void GDebug::Tracker::unTrack(void *object) {
70 int hash = ((unsigned)object >> 4) % size;
72 for (int k = 0; k < tracked[hash].size; ++k) {
73 if (tracked[hash].array[k].object == object) {
74 delete [] tracked[hash].array[k].context;
75 if (k < tracked[hash].size - 1)
76 memmove(tracked[hash].array + k, tracked[hash].array + k + 1,
77 (tracked[hash].size - k - 1) * sizeof(tracked[hash].array[0]));
78 --tracked[hash].size;
79 return;
83 Context::traceBack();
84 fprintf(stderr, "Object %lx has not been allocated !\n", object);
85 throw "Internal Error";
88 const char **GDebug::Context::save() {
89 int n = 0;
90 const char **p;
91 for (Context *c = current; c; c = c->prev)
92 ++n;
93 if (n) {
94 p = new const char * [n + 1];
95 if (p) {
96 const char **q = p + n;
97 *q = NULL;
98 for (Context *c = current; c; c = c->prev)
99 *--q = c->name;
101 } else
102 p = NULL;
103 return p;
106 void GDebug::Context::print(const char **context) {
107 fprintf(stderr, "*");
108 while (*context) {
109 fprintf(stderr, " / %s", *context);
110 ++context;
114 void GDebug::Context::traceBack() {
115 Context *context = current;
116 while (context) {
117 fprintf(stderr, "%s <- ", context->name);
118 context = context->prev;
120 fprintf(stderr, "*");
123 #endif