libdebug 0.0.1
Debugging helper library with Memory leak detection
memtrack.c
Go to the documentation of this file.
1
19#define _XOPEN_SOURCE 500 /* strdup */
20#include "libdebug/memtrack.h"
21#include <string.h> /* strdup */
22#include <stdio.h> /* fprintf */
23
24static TMemBlock *Head;
25static TMemBlock *Tail;
26static uint64_t NbBlocks;
27static uint64_t RAMSize;
29static unsigned int memtrack_init();
30static unsigned int memtrack_addblock_preinit(const void *p_Ptr,
31 const size_t p_Size,
32 const char *p_File,
33 const int p_Line,
34 const char *p_CompilDate,
35 const char *p_CompilTime,
36 const char *p_Function);
37static unsigned int memtrack_delblock_preinit(const void *p_Ptr,
38 const char *p_File,
39 const int p_Line,
40 const char *p_CompilDate,
41 const char *p_CompilTime,
42 const char *p_Function);
43static uint64_t memtrack_dumpblocks_preinit();
44static uint64_t memtrack_getallocatedblocks_preinit();
45static uint64_t memtrack_getallocatedRAM_preinit();
46static size_t memtrack_getblocksize_preinit(const void *p_Ptr);
47static unsigned int memtrack_addblock_postinit(const void *p_Ptr,
48 const size_t p_Size,
49 const char *p_File,
50 const int p_Line,
51 const char *p_CompilDate,
52 const char *p_CompilTime,
53 const char *p_Function);
54static unsigned int memtrack_delblock_postinit(const void *p_Ptr,
55 const char *p_File,
56 const int p_Line,
57 const char *p_CompilDate,
58 const char *p_CompilTime,
59 const char *p_Function);
60static uint64_t memtrack_dumpblocks_postinit();
61static uint64_t memtrack_getallocatedblocks_postinit();
62static uint64_t memtrack_getallocatedRAM_postinit();
63static size_t memtrack_getblocksize_postinit(const void *p_Ptr);
64
65/*******************/
66/* Implementations */
67/*******************/
68
76 /* Ne réinitialise que si nécessaire */
77 if ( memtrack_addblock == memtrack_addblock_preinit)
78 return;
79
80 /* Déconfiguration des foncteurs */
81 memtrack_addblock = memtrack_addblock_preinit;
82 memtrack_delblock = memtrack_delblock_preinit;
83 memtrack_dumpblocks = memtrack_dumpblocks_preinit;
84 memtrack_getallocatedblocks = memtrack_getallocatedblocks_preinit;
85 memtrack_getallocatedRAM = memtrack_getallocatedRAM_preinit;
86 memtrack_getblocksize = memtrack_getblocksize_preinit;
87
88 /* Purge de la liste */
89 while (Tail!=Head->Next) {
90 memtrack_delblock_postinit(Head->Next->Ptr,NULL,0,NULL,NULL,NULL);
91 }
92
93 /* Réinitialization des pointeurs */
94 free(Head);
95 free(Tail);
96 Head=NULL;
97 Tail=NULL;
98}
99
116static unsigned int memtrack_init() {
117 Head = (TMemBlock *) malloc(sizeof(TMemBlock));
118 Tail = (TMemBlock *) malloc(sizeof(TMemBlock));
119
120 if ((NULL==Head)||(NULL==Tail)) {
121 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
122 __FILE__,__LINE__);
123 return 1;
124 }
125 Head->Prev = (TMemBlock *) NULL;
126 Head->Next = Tail;
127 Tail->Next = (TMemBlock *) NULL;
128 Tail->Prev = Head;
129 Tail->Ptr = Head->Ptr = (void *)NULL;
130 Tail->Size = Head->Size = 0;
131 Tail->File = Head->File = (char *)NULL;
132 Tail->Line = Head->Line = 0;
133 Tail->CompilDate = Head->CompilDate = (char *)NULL;
134 Tail->CompilTime = Head->CompilTime = (char *)NULL;
135 Tail->Function = Head->Function = (char *)NULL;
136
137 /* Initialisation des compteurs */
138 NbBlocks=0;
139 RAMSize=0;
140
141 /* Modification des foncteurs pour utiliser les fonctions définitives */
142 memtrack_addblock = memtrack_addblock_postinit;
143 memtrack_delblock = memtrack_delblock_postinit;
144 memtrack_dumpblocks = memtrack_dumpblocks_postinit;
145 memtrack_getallocatedblocks = memtrack_getallocatedblocks_postinit;
146 memtrack_getallocatedRAM = memtrack_getallocatedRAM_postinit;
147 memtrack_getblocksize = memtrack_getblocksize_postinit;
148
149 return 0;
150}
151
152
164static unsigned int memtrack_addblock_preinit(const void *p_Ptr,
165 const size_t p_Size,
166 const char *p_File,
167 const int p_Line,
168 const char *p_CompilDate,
169 const char *p_CompilTime,
170 const char *p_Function) {
171 /* Initialisation de la liste */
172 if (0!=memtrack_init()) {
173 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
174 __FILE__,__LINE__);
175 /* OOM */
176 return 1;
177 }
178
179 /* Appel de la fonction réelle */
180 return memtrack_addblock(p_Ptr, p_Size, p_File, p_Line, p_CompilDate,
181 p_CompilTime, p_Function);
182}
183
195static unsigned int memtrack_delblock_preinit(const void *p_Ptr,
196 const char *p_File,
197 const int p_Line,
198 const char *p_CompilDate,
199 const char *p_CompilTime,
200 const char *p_Function) {
201 /* Initialisation de la liste */
202 if (0!=memtrack_init()) {
203 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
204 __FILE__,__LINE__);
205 /* OOM */
206 return 1;
207 }
208
209 /* Appel de la fonction réelle */
210 return memtrack_delblock(p_Ptr, p_File, p_Line, p_CompilDate,
211 p_CompilTime, p_Function);
212}
213
225static uint64_t memtrack_dumpblocks_preinit() {
226 /* Initialisation de la liste */
227 if (0!=memtrack_init()) {
228 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
229 __FILE__,__LINE__);
230 /* OOM */
231 return 0;
232 }
233
234 /* Appel de la fonction réelle */
235 return memtrack_dumpblocks();
236}
237
249static uint64_t memtrack_getallocatedblocks_preinit() {
250 /* Initialisation de la liste */
251 if (0!=memtrack_init()) {
252 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
253 __FILE__,__LINE__);
254 /* OOM */
255 return 0;
256 }
257
258 /* Appel de la fonction réelle */
260}
261
273static uint64_t memtrack_getallocatedRAM_preinit() {
274 /* Initialisation de la liste */
275 if (0!=memtrack_init()) {
276 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
277 __FILE__,__LINE__);
278 /* OOM */
279 return 0;
280 }
281
282 /* Appel de la fonction réelle */
284}
285
297static size_t memtrack_getblocksize_preinit(const void *p_Ptr) {
298 /* Initialisation de la liste */
299 if (0!=memtrack_init()) {
300 fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
301 __FILE__,__LINE__);
302 /* OOM */
303 return 0;
304 }
305
306 /* Appel de la fonction réelle */
307 return memtrack_getblocksize(p_Ptr);
308}
309
318static unsigned int memtrack_addblock_postinit(const void *p_Ptr,
319 const size_t p_Size,
320 const char *p_File,
321 const int p_Line,
322 const char *p_CompilDate,
323 const char *p_CompilTime,
324 const char *p_Function) {
325 TMemBlock *l_tmp;
326
327 /* Test de validité des données à enregistrer */
328 /* Meme si malloc permet Size=0, ce n'est pas portable */
329 if ((NULL==p_Ptr)||
330 (0==p_Size)||
331 (NULL==p_File)||
332 (0==p_File[0])||
333 (0==p_Line)||
334 (NULL==p_CompilDate)||
335 (0==p_CompilDate[0])||
336 (NULL==p_CompilTime)||
337 (0==p_CompilTime[0])||
338 (NULL==p_Function)||
339 (0==p_Function[0])) {
340 fprintf(stderr,"%s:%d Null or empty parameters\n",__FILE__, __LINE__);
341 return 1;
342 }
343
344 /* On ne peut pas dupliquer un pointeur. Pour le modifier, il faut le
345 * supprimer et le recréer, ce n'est pas le rôle de ces fonctions de
346 * bas-niveau */
347
348 /* Recherche du pointeur */
349 l_tmp = Head->Next;
350 while ((l_tmp->Ptr != p_Ptr) && (l_tmp != Tail))
351 l_tmp = l_tmp->Next;
352
353 /* Le bloc ne doit pas avoir été trouvé */
354 if (l_tmp != Tail) {
355 fprintf(stderr,"%s:%d Memory bloc already registered\n",__FILE__, __LINE__);
356 return 1;
357 }
358
359 /* Allocation d'un nouveau descripteur de bloc */
360 l_tmp = (TMemBlock *) malloc(sizeof(TMemBlock));
361
362 /* Allocation réussie ? */
363 if (NULL == l_tmp) {
364 return 1;
365 }
366
367 /* Remplissage du descripteur */
368 l_tmp->Ptr = (void *)p_Ptr;
369 l_tmp->Size = p_Size;
370 if (NULL==(l_tmp->File = strdup(p_File?p_File:""))) {
371 free(l_tmp);
372 return 1;
373 };
374 l_tmp->Line = p_Line;
375 if (NULL==(l_tmp->CompilDate = strdup(p_CompilDate?p_CompilDate:""))) {
376 free(l_tmp->File);
377 free(l_tmp);
378 return 1;
379 };
380 if (NULL==(l_tmp->CompilTime = strdup(p_CompilTime?p_CompilTime:""))) {
381 free(l_tmp->CompilDate);
382 free(l_tmp->File);
383 free(l_tmp);
384 return 1;
385 };
386 if (NULL==(l_tmp->Function = strdup(p_Function?p_Function:""))) {
387 free(l_tmp->CompilTime);
388 free(l_tmp->CompilDate);
389 free(l_tmp->File);
390 free(l_tmp);
391 return 1;
392 };
393
394 /* Ajout de la description dans la liste (Section critique) */
395 l_tmp->Prev = Tail->Prev;
396 l_tmp->Next = Tail;
397 l_tmp->Prev->Next = l_tmp->Next->Prev = l_tmp;
398
399 /* Mise à jour des compteurs */
400 NbBlocks++;
401 RAMSize += p_Size;
402
403 return 0;
404}
405
414static unsigned int memtrack_delblock_postinit(const void *p_Ptr,
415 const char *p_File,
416 const int p_Line,
417 const char *p_CompilDate,
418 const char *p_CompilTime,
419 const char *p_Function) {
420 TMemBlock *l_tmp;
421 (void) p_File;
422 (void) p_Line;
423 (void) p_CompilDate;
424 (void) p_CompilTime;
425 (void) p_Function;
426
427 /* Recherche de la description */
428 l_tmp = Head->Next;
429 while ((l_tmp->Ptr != p_Ptr) && (l_tmp != Tail))
430 l_tmp = l_tmp->Next;
431
432 /* Le bloc doit avoir été trouvé */
433 if (l_tmp == Tail) {
434 fprintf(stderr,"%s:%d Block not found for deletion\n",__FILE__, __LINE__);
435 return 1;
436 }
437
438 /* Libération des ressources acquises */
439 /* On ne libère pas le bloc mémoire lui-même */
440 free(l_tmp->File);
441 free(l_tmp->CompilDate);
442 free(l_tmp->CompilTime);
443 free(l_tmp->Function);
444
445 /* Retrait de la description de la liste (Section critique) */
446 l_tmp->Next->Prev = l_tmp->Prev;
447 l_tmp->Prev->Next = l_tmp->Next;
448
449 /* Mise à jour des compteurs */
450 NbBlocks--;
451 RAMSize -= l_tmp->Size;
452
453 /* Libération de la description */
454 free(l_tmp);
455
456 return 0;
457}
458
467static uint64_t memtrack_dumpblocks_postinit() {
468 TMemBlock *l_tmp;
469 uint64_t l_NbBlocks = 0;;
470
471 if (Head->Next != Tail) {
472 size_t l_BlockSize;
473 fprintf(stderr,
474 "+----------------------------------------------------------------------------------------------------------+\n");
475 fprintf(stderr, "| %-104s |\n", "Memory Tracker Report");
476 fprintf(stderr,
477 "+----------------------+----------------------+------+-----------------+----------+------------------------+\n");
478 fprintf(stderr,
479 "| %-20s | %-20s | %-4s | %-15s | %-8s | %-22s |\n",
480 "Function", "File", "Line", "Address", "Bytes",
481 "Compiled");
482 fprintf(stderr,
483 "+----------------------+----------------------+------+-----------------+----------+------------------------+\n");
484
485 l_tmp = Head->Next;
486 l_BlockSize = 0;
487 while (l_tmp != Tail) {
488 fprintf(stderr,
489 "| %-20s | %-20s | %4d | %15p | %8lu | %11s @ %8s |\n",
490 l_tmp->Function, l_tmp->File, l_tmp->Line,
491 l_tmp->Ptr, (unsigned long)l_tmp->Size, l_tmp->CompilDate,
492 l_tmp->CompilTime);
493 l_NbBlocks++;
494 l_BlockSize += l_tmp->Size;
495 l_tmp = l_tmp->Next;
496 }
497 fprintf(stderr,
498 "+----------------------+----------------------+------+-----------------+----------+------------------------+\n");
499 fprintf(stderr,
500 "| %9lu bytes in %6lu blocks. %70s |\n", (unsigned long)l_BlockSize,
501 (unsigned long)l_NbBlocks, "");
502 fprintf(stderr,
503 "+----------------------------------------------------------------------------------------------------------+\n");
504 }
505 /* Add ASSERT or assert (l_NbBlocks==NbBlocks) */
506 return l_NbBlocks;
507}
508
517static uint64_t memtrack_getallocatedblocks_postinit() {
518 return NbBlocks;
519}
520
529static uint64_t memtrack_getallocatedRAM_postinit() {
530 return RAMSize;
531}
532
541static size_t memtrack_getblocksize_postinit(const void *p_Ptr) {
542 /* Recherche de la description */
543 TMemBlock *l_tmp = Head->Next;
544 while ((l_tmp->Ptr != p_Ptr) && (l_tmp != Tail))
545 l_tmp = l_tmp->Next;
546
547 /* Le bloc doit avoir été trouvé */
548 if (l_tmp == Tail)
549 return 0;
550 else
551 return l_tmp->Size;
552}
553
584unsigned int (*memtrack_addblock) (const void *p_Ptr,
585 const size_t p_Size,
586 const char *p_File,
587 const int p_Line,
588 const char *p_CompilDate,
589 const char *p_CompilTime,
590 const char *p_Function) =
591 memtrack_addblock_preinit;
592
621unsigned int (*memtrack_delblock) (const void *p_Ptr,
622 const char *p_File,
623 const int p_Line,
624 const char *p_CompilDate,
625 const char *p_CompilTime,
626 const char *p_Function) =
627 memtrack_delblock_preinit;
628
642uint64_t (*memtrack_dumpblocks) () = memtrack_dumpblocks_preinit;
643
656uint64_t (*memtrack_getallocatedblocks) () = memtrack_getallocatedblocks_preinit;
657
670uint64_t (*memtrack_getallocatedRAM) () = memtrack_getallocatedRAM_preinit;
671
689size_t(*memtrack_getblocksize) (const void *p_Ptr) = memtrack_getblocksize_preinit;
690
691/* vim: set tw=80: */
#define malloc(size)
Same syntaxt and same behavior than regular malloc function, with memory leaks tracking.
Definition: memory.h:32
#define strdup(chaine)
Same syntaxt and same behavior than regular strdup function, with memory leaks tracking.
Definition: memory.h:44
#define free(ptr)
Same syntaxt and same behavior than regular free function, with memory leaks tracking.
Definition: memory.h:41
size_t(* memtrack_getblocksize)(const void *p_Ptr)
Functor to get size of a specific memory block.
Definition: memtrack.c:689
void memtrack_reset()
Memory block metadata list reset.
Definition: memtrack.c:75
uint64_t(* memtrack_getallocatedblocks)()
Functor to get the number of allocated blocks.
Definition: memtrack.c:656
uint64_t(* memtrack_getallocatedRAM)()
Functor to get the total RAM size allocated.
Definition: memtrack.c:670
unsigned int(* memtrack_delblock)(const void *p_Ptr, const char *p_File, const int p_Line, const char *p_CompilDate, const char *p_CompilTime, const char *p_Function)
Functor to unregister an allocated memory block metadata.
Definition: memtrack.c:621
uint64_t(* memtrack_dumpblocks)()
Functor to list allocated memory blocks metadata.
Definition: memtrack.c:642
unsigned int(* memtrack_addblock)(const void *p_Ptr, const size_t p_Size, const char *p_File, const int p_Line, const char *p_CompilDate, const char *p_CompilTime, const char *p_Function)
Functor to register an allocated memory block metadata.
Definition: memtrack.c:584
Memory block metadata tracking headers.
Memory block metadata list item.
Definition: memtrack.h:33
size_t Size
Allocated memory block size.
Definition: memtrack.h:37
struct MemBlock * Prev
Previous item pointer.
Definition: memtrack.h:34
struct MemBlock * Next
Next item pointer.
Definition: memtrack.h:35
char * CompilDate
Source file compilation date.
Definition: memtrack.h:40
char * CompilTime
Source file compilation time.
Definition: memtrack.h:41
char * File
Source file which asked the allocation.
Definition: memtrack.h:38
char * Function
Fonction name which asked the allocation.
Definition: memtrack.h:42
void * Ptr
Allocated memory block pointer.
Definition: memtrack.h:36
int Line
Source line number ch asked the allocation.
Definition: memtrack.h:39