DebugMemory.c 5.97 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
3
4
5
6
/*
htop - DebugMemory.c
(C) 2004-2011 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/
Hisham Muhammad's avatar
Hisham Muhammad committed
7

8
#include <string.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
9
10
11
12
13
14
15
16
17
18
19
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>

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

20
21
#include "DebugMemory.h"

Hisham Muhammad's avatar
Hisham Muhammad committed
22
/*{
23

Hisham Muhammad's avatar
Hisham Muhammad committed
24
25
26
typedef struct DebugMemoryItem_ DebugMemoryItem;

struct DebugMemoryItem_ {
27
   int magic;
Hisham Muhammad's avatar
Hisham Muhammad committed
28
29
30
31
32
33
34
35
36
37
38
   void* data;
   char* file;
   int line;
   DebugMemoryItem* next;
};

typedef struct DebugMemory_ {
   DebugMemoryItem* first;
   int allocations;
   int deallocations;
   int size;
39
   bool totals;
Hisham Muhammad's avatar
Hisham Muhammad committed
40
41
   FILE* file;
} DebugMemory;
42

Hisham Muhammad's avatar
Hisham Muhammad committed
43
44
}*/

45
46
47
#if defined(DEBUG)

static DebugMemory* singleton = NULL;
Hisham Muhammad's avatar
Hisham Muhammad committed
48
49
50
51
52
53
54
55
56

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

66
void* DebugMemory_malloc(int size, char* file, int line, char* str) {
Hisham Muhammad's avatar
Hisham Muhammad committed
67
68
   void* data = malloc(size);
   DebugMemory_registerAllocation(data, file, line);
69
70
71
72
   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
73
74
75
76
77
78
   return data;
}

void* DebugMemory_calloc(int a, int b, char* file, int line) {
   void* data = calloc(a, b);
   DebugMemory_registerAllocation(data, file, line);
79
80
81
82
   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
83
84
85
   return data;
}

86
void* DebugMemory_realloc(void* ptr, int size, char* file, int line, char* str) {
Hisham Muhammad's avatar
Hisham Muhammad committed
87
88
89
90
   if (ptr != NULL)
      DebugMemory_registerDeallocation(ptr, file, line);
   void* data = realloc(ptr, size);
   DebugMemory_registerAllocation(data, file, line);
91
92
93
94
   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
95
96
97
   return data;
}

98
void* DebugMemory_strdup(const char* str, char* file, int line) {
99
   assert(str);
Hisham Muhammad's avatar
Hisham Muhammad committed
100
101
   char* data = strdup(str);
   DebugMemory_registerAllocation(data, file, line);
102
103
104
105
   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
106
107
108
109
   return data;
}

void DebugMemory_free(void* data, char* file, int line) {
110
   if (!data) return;
Hisham Muhammad's avatar
Hisham Muhammad committed
111
   DebugMemory_registerDeallocation(data, file, line);
112
113
114
115
   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
116
117
118
119
120
121
122
123
124
125
   free(data);
}

void DebugMemory_assertSize() {
   if (!singleton->first) {
      assert (singleton->size == 0);
   }
   DebugMemoryItem* walk = singleton->first;
   int i = 0;
   while (walk != NULL) {
126
      assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
127
128
129
130
131
132
133
134
135
136
137
138
139
      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) {
140
      assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
141
142
143
144
145
146
147
148
149
150
151
      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));
152
   item->magic = 11061980;
Hisham Muhammad's avatar
Hisham Muhammad committed
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
   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;
         }
168
         assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
         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) {
186
      assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
      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) {
214
      assert(walk->magic == 11061980);
Hisham Muhammad's avatar
Hisham Muhammad committed
215
216
      i++;
      fprintf(stderr, "%p %s:%d\n", walk->data, walk->file, walk->line);
217
      DebugMemoryItem* old = walk;
Hisham Muhammad's avatar
Hisham Muhammad committed
218
      walk = walk->next;
219
220
      free(old->file);
      free(old);
Hisham Muhammad's avatar
Hisham Muhammad committed
221
222
223
224
225
226
   }
   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);
227
228
   if (singleton->file)
      fclose(singleton->file);
229
   free(singleton);
Hisham Muhammad's avatar
Hisham Muhammad committed
230
}
231
232
233
234
235
236

#elif defined(DEBUGLITE)

//#include "efence.h"

#endif