DebugMemory.c 5.82 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1

2
#include <string.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
3
4
5
6
7
8
9
10
11
12
13
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>

#undef strdup
#undef malloc
#undef realloc
#undef calloc
#undef free

14
15
#include "DebugMemory.h"

Hisham Muhammad's avatar
Hisham Muhammad committed
16
/*{
17

Hisham Muhammad's avatar
Hisham Muhammad committed
18
19
20
typedef struct DebugMemoryItem_ DebugMemoryItem;

struct DebugMemoryItem_ {
21
   int magic;
Hisham Muhammad's avatar
Hisham Muhammad committed
22
23
24
25
26
27
28
29
30
31
32
   void* data;
   char* file;
   int line;
   DebugMemoryItem* next;
};

typedef struct DebugMemory_ {
   DebugMemoryItem* first;
   int allocations;
   int deallocations;
   int size;
33
   bool totals;
Hisham Muhammad's avatar
Hisham Muhammad committed
34
35
   FILE* file;
} DebugMemory;
36

Hisham Muhammad's avatar
Hisham Muhammad committed
37
38
}*/

39
40
41
#if defined(DEBUG)

static DebugMemory* singleton = NULL;
Hisham Muhammad's avatar
Hisham Muhammad committed
42
43
44
45
46
47
48
49
50

void DebugMemory_new() {
   if (singleton)
      return;
   singleton = malloc(sizeof(DebugMemory));
   singleton->first = NULL;
   singleton->allocations = 0;
   singleton->deallocations = 0;
   singleton->size = 0;
51
   #ifdef DEBUG_ALLOC
Hisham Muhammad's avatar
Hisham Muhammad committed
52
   singleton->file = fopen("/tmp/htop-debug-alloc.txt", "w");
53
54
55
   #else
   singleton->file = NULL;
   #endif
56
57
   singleton->totals = true;
   //singleton->file = NULL;
Hisham Muhammad's avatar
Hisham Muhammad committed
58
59
}

60
void* DebugMemory_malloc(int size, char* file, int line, char* str) {
Hisham Muhammad's avatar
Hisham Muhammad committed
61
62
   void* data = malloc(size);
   DebugMemory_registerAllocation(data, file, line);
63
64
65
66
   if (singleton->file) {
      if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
      fprintf(singleton->file, "%d\t%s:%d (%s)\n", size, file, line, str);
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
67
68
69
70
71
72
   return data;
}

void* DebugMemory_calloc(int a, int b, char* file, int line) {
   void* data = calloc(a, b);
   DebugMemory_registerAllocation(data, file, line);
73
74
75
76
   if (singleton->file) {
      if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
      fprintf(singleton->file, "%d\t%s:%d\n", a*b, file, line);
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
77
78
79
   return data;
}

80
void* DebugMemory_realloc(void* ptr, int size, char* file, int line, char* str) {
Hisham Muhammad's avatar
Hisham Muhammad committed
81
82
83
84
   if (ptr != NULL)
      DebugMemory_registerDeallocation(ptr, file, line);
   void* data = realloc(ptr, size);
   DebugMemory_registerAllocation(data, file, line);
85
86
87
88
   if (singleton->file) {
      if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
      fprintf(singleton->file, "%d\t%s:%d (%s)\n", size, file, line, str);
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
89
90
91
   return data;
}

92
void* DebugMemory_strdup(const char* str, char* file, int line) {
93
   assert(str);
Hisham Muhammad's avatar
Hisham Muhammad committed
94
95
   char* data = strdup(str);
   DebugMemory_registerAllocation(data, file, line);
96
97
98
99
   if (singleton->file) {
      if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
      fprintf(singleton->file, "%d\t%s:%d\n", (int) strlen(str), file, line);
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
100
101
102
103
   return data;
}

void DebugMemory_free(void* data, char* file, int line) {
104
   if (!data) return;
Hisham Muhammad's avatar
Hisham Muhammad committed
105
   DebugMemory_registerDeallocation(data, file, line);
106
107
108
109
   if (singleton->file) {
      if (singleton->totals) fprintf(singleton->file, "%d\t", singleton->size);
      fprintf(singleton->file, "free\t%s:%d\n", file, line);
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
110
111
112
113
114
115
116
117
118
119
   free(data);
}

void DebugMemory_assertSize() {
   if (!singleton->first) {
      assert (singleton->size == 0);
   }
   DebugMemoryItem* walk = singleton->first;
   int i = 0;
   while (walk != NULL) {
120
      assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
121
122
123
124
125
126
127
128
129
130
131
132
133
      i++;
      walk = walk->next;
   }
   assert (i == singleton->size);
}

int DebugMemory_getBlockCount() {
   if (!singleton->first) {
      return 0;
   }
   DebugMemoryItem* walk = singleton->first;
   int i = 0;
   while (walk != NULL) {
134
      assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
135
136
137
138
139
140
141
142
143
144
145
      i++;
      walk = walk->next;
   }
   return i;
}

void DebugMemory_registerAllocation(void* data, char* file, int line) {
   if (!singleton)
      DebugMemory_new();
   DebugMemory_assertSize();
   DebugMemoryItem* item = (DebugMemoryItem*) malloc(sizeof(DebugMemoryItem));
146
   item->magic = 11061980;
Hisham Muhammad's avatar
Hisham Muhammad committed
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
   item->data = data;
   item->file = file;
   item->line = line;
   item->next = NULL;
   int val = DebugMemory_getBlockCount();
   if (singleton->first == NULL) {
      assert (val == 0);
      singleton->first = item;
   } else {
      DebugMemoryItem* walk = singleton->first;
      while (true) {
         if (walk->next == NULL) {
            walk->next = item;
            break;
         }
162
         assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
         walk = walk->next;
      }
   }
   int nval = DebugMemory_getBlockCount();
   assert(nval == val + 1);
   singleton->allocations++;
   singleton->size++;
   DebugMemory_assertSize();
}

void DebugMemory_registerDeallocation(void* data, char* file, int line) {
   assert(singleton);
   assert(singleton->first);
   DebugMemoryItem* walk = singleton->first;
   DebugMemoryItem* prev = NULL;
   int val = DebugMemory_getBlockCount();
   while (walk != NULL) {
180
      assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
      if (walk->data == data) {
         if (prev == NULL) {
            singleton->first = walk->next;
         } else {
            prev->next = walk->next;
         }
         free(walk);
         assert(DebugMemory_getBlockCount() == val - 1);
         singleton->deallocations++;
         singleton->size--;
         DebugMemory_assertSize();
         return;
      }
      DebugMemoryItem* tmp = walk;
      walk = walk->next;
      prev = tmp;
   }
   DebugMemory_report();
   fprintf(stderr, "Couldn't find allocation for memory freed at %s:%d\n", file, line);
   assert(false);
}

void DebugMemory_report() {
   assert(singleton);
   DebugMemoryItem* walk = singleton->first;
   int i = 0;
   while (walk != NULL) {
208
      assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
209
210
      i++;
      fprintf(stderr, "%p %s:%d\n", walk->data, walk->file, walk->line);
211
      DebugMemoryItem* old = walk;
Hisham Muhammad's avatar
Hisham Muhammad committed
212
      walk = walk->next;
213
214
      free(old->file);
      free(old);
Hisham Muhammad's avatar
Hisham Muhammad committed
215
216
217
218
219
220
   }
   fprintf(stderr, "Total:\n");
   fprintf(stderr, "%d allocations\n", singleton->allocations);
   fprintf(stderr, "%d deallocations\n", singleton->deallocations);
   fprintf(stderr, "%d size\n", singleton->size);
   fprintf(stderr, "%d non-freed blocks\n", i);
221
222
   if (singleton->file)
      fclose(singleton->file);
223
   free(singleton);
Hisham Muhammad's avatar
Hisham Muhammad committed
224
}
225
226
227
228
229
230

#elif defined(DEBUGLITE)

//#include "efence.h"

#endif