Line data Source code
1 : /** @file memtrack.c
2 : * @brief Memory block metadata tracking implementation
3 : * @date 25/09/2006
4 : * @author François Cerbelle (Fanfan), francois@cerbelle.net
5 : * @copyright Copyright (c) 1997-2024, François Cerbelle
6 : *
7 : * Originally inspired by "L'art du code", Steve Maguire, Microsoft Press
8 : *
9 : * @internal
10 : * Compiler gcc
11 : * Last modified 2024-12-19 19:49
12 : * Organization Cerbelle.net
13 : * Company Home
14 : *
15 : * This source code is released for free distribution under the terms of the
16 : * GNU General Public License as published by the Free Software Foundation.
17 : */
18 :
19 : #define _XOPEN_SOURCE 500 /* strdup */
20 : #include "libdebug/memtrack.h"
21 : #include <string.h> /* strdup */
22 : #include <stdio.h> /* fprintf */
23 :
24 : static TMemBlock *Head; /**< Memory blocks metadata list start sentinal */
25 : static TMemBlock *Tail; /**< Memory blocks metadata list end sentinal */
26 : static uint64_t NbBlocks; /**< Memory blocks metadata counter */
27 : static uint64_t RAMSize; /**< Memory blocks metadata RAM sum */
28 :
29 : static unsigned int memtrack_init();
30 : static 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);
37 : static 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);
43 : static uint64_t memtrack_dumpblocks_preinit();
44 : static uint64_t memtrack_getallocatedblocks_preinit();
45 : static uint64_t memtrack_getallocatedRAM_preinit();
46 : static size_t memtrack_getblocksize_preinit(const void *p_Ptr);
47 : static 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);
54 : static 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);
60 : static uint64_t memtrack_dumpblocks_postinit();
61 : static uint64_t memtrack_getallocatedblocks_postinit();
62 : static uint64_t memtrack_getallocatedRAM_postinit();
63 : static size_t memtrack_getblocksize_postinit(const void *p_Ptr);
64 :
65 : /*******************/
66 : /* Implementations */
67 : /*******************/
68 :
69 : /** Memory block metadata list reset
70 : *
71 : * This function is not defined in the header file because it should never be
72 : * used. It is exported because it is used by the unit tests. NEVER USE IT, it
73 : * will crash your code.
74 : */
75 204 : void memtrack_reset() {
76 : /* Ne réinitialise que si nécessaire */
77 204 : if ( memtrack_addblock == memtrack_addblock_preinit)
78 102 : return;
79 :
80 : /* Déconfiguration des foncteurs */
81 102 : memtrack_addblock = memtrack_addblock_preinit;
82 102 : memtrack_delblock = memtrack_delblock_preinit;
83 102 : memtrack_dumpblocks = memtrack_dumpblocks_preinit;
84 102 : memtrack_getallocatedblocks = memtrack_getallocatedblocks_preinit;
85 102 : memtrack_getallocatedRAM = memtrack_getallocatedRAM_preinit;
86 102 : memtrack_getblocksize = memtrack_getblocksize_preinit;
87 :
88 : /* Purge de la liste */
89 282 : while (Tail!=Head->Next) {
90 180 : memtrack_delblock_postinit(Head->Next->Ptr,NULL,0,NULL,NULL,NULL);
91 : }
92 :
93 : /* Réinitialization des pointeurs */
94 102 : free(Head);
95 102 : free(Tail);
96 102 : Head=NULL;
97 102 : Tail=NULL;
98 : }
99 :
100 : /** Memory blocks metadata list initialization
101 : *
102 : * This function is private, not meant to be called externally, it is
103 : * automatically called by other functions at the very first usage. It
104 : * initializes the memory block metadata list, with start and end sentinels. It
105 : * needs to be executed before the real list manipulation functions.
106 : *
107 : * Each real manipulation function has two private static implementations,
108 : * uninitialized and initialized, and a publicly exported functor which is
109 : * referencing the uninitialized form by default. The uninitialized forms first
110 : * call this initialization function which makes the functos reference the
111 : * initialized forms.
112 : *
113 : * \return Initialization status
114 : * \retval 0 in case of success
115 : */
116 393 : static unsigned int memtrack_init() {
117 393 : Head = (TMemBlock *) malloc(sizeof(TMemBlock));
118 393 : Tail = (TMemBlock *) malloc(sizeof(TMemBlock));
119 :
120 393 : if ((NULL==Head)||(NULL==Tail)) {
121 0 : fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
122 : __FILE__,__LINE__);
123 0 : return 1;
124 : }
125 393 : Head->Prev = (TMemBlock *) NULL;
126 393 : Head->Next = Tail;
127 393 : Tail->Next = (TMemBlock *) NULL;
128 393 : Tail->Prev = Head;
129 393 : Tail->Ptr = Head->Ptr = (void *)NULL;
130 393 : Tail->Size = Head->Size = 0;
131 393 : Tail->File = Head->File = (char *)NULL;
132 393 : Tail->Line = Head->Line = 0;
133 393 : Tail->CompilDate = Head->CompilDate = (char *)NULL;
134 393 : Tail->CompilTime = Head->CompilTime = (char *)NULL;
135 393 : Tail->Function = Head->Function = (char *)NULL;
136 :
137 : /* Initialisation des compteurs */
138 393 : NbBlocks=0;
139 393 : RAMSize=0;
140 :
141 : /* Modification des foncteurs pour utiliser les fonctions définitives */
142 393 : memtrack_addblock = memtrack_addblock_postinit;
143 393 : memtrack_delblock = memtrack_delblock_postinit;
144 393 : memtrack_dumpblocks = memtrack_dumpblocks_postinit;
145 393 : memtrack_getallocatedblocks = memtrack_getallocatedblocks_postinit;
146 393 : memtrack_getallocatedRAM = memtrack_getallocatedRAM_postinit;
147 393 : memtrack_getblocksize = memtrack_getblocksize_postinit;
148 :
149 393 : return 0;
150 : }
151 :
152 :
153 : /** Add a memory block metadata entry to the list (preinit)
154 : *
155 : * Default function for the memtrack_addblock functor until initialized by the
156 : * memtrack_init function. It is executed if the functor is called before
157 : * initialization. It triggers initialization with functors definitive
158 : * assignation to the *_postinit functions and calls the actual postinit
159 : * function.
160 : *
161 : * \sa memtrack_addblock
162 : * \sa memtrack_addblock_postinit
163 : */
164 70 : static 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 70 : if (0!=memtrack_init()) {
173 0 : fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
174 : __FILE__,__LINE__);
175 : /* OOM */
176 0 : return 1;
177 : }
178 :
179 : /* Appel de la fonction réelle */
180 70 : return memtrack_addblock(p_Ptr, p_Size, p_File, p_Line, p_CompilDate,
181 : p_CompilTime, p_Function);
182 : }
183 :
184 : /** Remove a memory block metadata entry from the list (preinit)
185 : *
186 : * Default function for the memtrack_delblock functor until initialized by the
187 : * memtrack_init function. It is executed if the functor is called before
188 : * initialization. It triggers initialization with functors definitive
189 : * assignation to the *_postinit functions and calls the actual postinit
190 : * function.
191 : *
192 : * \sa memtrack_delblock
193 : * \sa memtrack_delblock_postinit
194 : */
195 4 : static 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 4 : if (0!=memtrack_init()) {
203 0 : fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
204 : __FILE__,__LINE__);
205 : /* OOM */
206 0 : return 1;
207 : }
208 :
209 : /* Appel de la fonction réelle */
210 4 : return memtrack_delblock(p_Ptr, p_File, p_Line, p_CompilDate,
211 : p_CompilTime, p_Function);
212 : }
213 :
214 : /** Dump memory block metadata entries from the list (preinit)
215 : *
216 : * Default function for the memtrack_dumpblocks functor until initialized by the
217 : * memtrack_init function. It is executed if the functor is called before
218 : * initialization. It triggers initialization with functors definitive
219 : * assignation to the *_postinit functions and calls the actual postinit
220 : * function.
221 : *
222 : * \sa memtrack_dumpblocks
223 : * \sa memtrack_dumpblocks_postinit
224 : */
225 2 : static uint64_t memtrack_dumpblocks_preinit() {
226 : /* Initialisation de la liste */
227 2 : if (0!=memtrack_init()) {
228 0 : fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
229 : __FILE__,__LINE__);
230 : /* OOM */
231 0 : return 0;
232 : }
233 :
234 : /* Appel de la fonction réelle */
235 2 : return memtrack_dumpblocks();
236 : }
237 :
238 : /** Get the memory block metadata entries count (preinit)
239 : *
240 : * Default function for the memtrack_getallocatedblocks functor until
241 : * initialized by the memtrack_init function. It is executed if the functor is
242 : * called before initialization. It triggers initialization with functors
243 : * definitive assignation to the *_postinit functions and calls the actual
244 : * postinit function.
245 : *
246 : * \sa memtrack_getallocatedblocks
247 : * \sa memtrack_getallocatedblocks_postinit
248 : */
249 306 : static uint64_t memtrack_getallocatedblocks_preinit() {
250 : /* Initialisation de la liste */
251 306 : if (0!=memtrack_init()) {
252 0 : fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
253 : __FILE__,__LINE__);
254 : /* OOM */
255 0 : return 0;
256 : }
257 :
258 : /* Appel de la fonction réelle */
259 306 : return memtrack_getallocatedblocks();
260 : }
261 :
262 : /** Get the memory block metadata entries total RAM (preinit)
263 : *
264 : * Default function for the memtrack_getallocatedRAM functor until
265 : * initialized by the memtrack_init function. It is executed if the functor is
266 : * called before initialization. It triggers initialization with functors
267 : * definitive assignation to the *_postinit functions and calls the actual
268 : * postinit function.
269 : *
270 : * \sa memtrack_getallocatedRAM
271 : * \sa memtrack_getallocatedRAM_postinit
272 : */
273 3 : static uint64_t memtrack_getallocatedRAM_preinit() {
274 : /* Initialisation de la liste */
275 3 : if (0!=memtrack_init()) {
276 0 : fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
277 : __FILE__,__LINE__);
278 : /* OOM */
279 0 : return 0;
280 : }
281 :
282 : /* Appel de la fonction réelle */
283 3 : return memtrack_getallocatedRAM();
284 : }
285 :
286 : /** Get a memory block RAM size (preinit)
287 : *
288 : * Default function for the memtrack_getblocksize functor until initialized by
289 : * the memtrack_init function. It is executed if the functor is called before
290 : * initialization. It triggers initialization with functors definitive
291 : * assignation to the *_postinit functions and calls the actual postinit
292 : * function.
293 : *
294 : * \sa memtrack_getblocksize
295 : * \sa memtrack_getblocksize_postinit
296 : */
297 8 : static size_t memtrack_getblocksize_preinit(const void *p_Ptr) {
298 : /* Initialisation de la liste */
299 8 : if (0!=memtrack_init()) {
300 0 : fprintf(stderr,"%s:%d Not enough memory to initialize memtracker\n",
301 : __FILE__,__LINE__);
302 : /* OOM */
303 0 : return 0;
304 : }
305 :
306 : /* Appel de la fonction réelle */
307 8 : return memtrack_getblocksize(p_Ptr);
308 : }
309 :
310 : /** Add a memory block metadata entry to the list (postinit)
311 : *
312 : * This function is referenced by the memtrack_addblock functor after
313 : * initialization. This is the real implementation of the feature.
314 : *
315 : * \sa memtrack_addblock
316 : * \sa memtrack_addblock_preinit
317 : */
318 1110 : static 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 1110 : if ((NULL==p_Ptr)||
330 1044 : (0==p_Size)||
331 1032 : (NULL==p_File)||
332 1032 : (0==p_File[0])||
333 954 : (0==p_Line)||
334 942 : (NULL==p_CompilDate)||
335 942 : (0==p_CompilDate[0])||
336 894 : (NULL==p_CompilTime)||
337 894 : (0==p_CompilTime[0])||
338 846 : (NULL==p_Function)||
339 846 : (0==p_Function[0])) {
340 300 : fprintf(stderr,"%s:%d Null or empty parameters\n",__FILE__, __LINE__);
341 300 : 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 810 : l_tmp = Head->Next;
350 2271 : while ((l_tmp->Ptr != p_Ptr) && (l_tmp != Tail))
351 1461 : l_tmp = l_tmp->Next;
352 :
353 : /* Le bloc ne doit pas avoir été trouvé */
354 810 : if (l_tmp != Tail) {
355 6 : fprintf(stderr,"%s:%d Memory bloc already registered\n",__FILE__, __LINE__);
356 6 : return 1;
357 : }
358 :
359 : /* Allocation d'un nouveau descripteur de bloc */
360 804 : l_tmp = (TMemBlock *) malloc(sizeof(TMemBlock));
361 :
362 : /* Allocation réussie ? */
363 804 : if (NULL == l_tmp) {
364 0 : return 1;
365 : }
366 :
367 : /* Remplissage du descripteur */
368 804 : l_tmp->Ptr = (void *)p_Ptr;
369 804 : l_tmp->Size = p_Size;
370 804 : if (NULL==(l_tmp->File = strdup(p_File?p_File:""))) {
371 0 : free(l_tmp);
372 0 : return 1;
373 : };
374 804 : l_tmp->Line = p_Line;
375 804 : if (NULL==(l_tmp->CompilDate = strdup(p_CompilDate?p_CompilDate:""))) {
376 0 : free(l_tmp->File);
377 0 : free(l_tmp);
378 0 : return 1;
379 : };
380 804 : if (NULL==(l_tmp->CompilTime = strdup(p_CompilTime?p_CompilTime:""))) {
381 0 : free(l_tmp->CompilDate);
382 0 : free(l_tmp->File);
383 0 : free(l_tmp);
384 0 : return 1;
385 : };
386 804 : if (NULL==(l_tmp->Function = strdup(p_Function?p_Function:""))) {
387 0 : free(l_tmp->CompilTime);
388 0 : free(l_tmp->CompilDate);
389 0 : free(l_tmp->File);
390 0 : free(l_tmp);
391 0 : return 1;
392 : };
393 :
394 : /* Ajout de la description dans la liste (Section critique) */
395 804 : l_tmp->Prev = Tail->Prev;
396 804 : l_tmp->Next = Tail;
397 804 : l_tmp->Prev->Next = l_tmp->Next->Prev = l_tmp;
398 :
399 : /* Mise à jour des compteurs */
400 804 : NbBlocks++;
401 804 : RAMSize += p_Size;
402 :
403 804 : return 0;
404 : }
405 :
406 : /** Remove a memory block metadata entry from the list (postinit)
407 : *
408 : * This function is referenced by the memtrack_addblock functor after
409 : * initialization. This is the real implementation of the feature.
410 : *
411 : * \sa memtrack_delblock
412 : * \sa memtrack_delblock_preinit
413 : */
414 770 : static 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 770 : l_tmp = Head->Next;
429 1179 : while ((l_tmp->Ptr != p_Ptr) && (l_tmp != Tail))
430 409 : l_tmp = l_tmp->Next;
431 :
432 : /* Le bloc doit avoir été trouvé */
433 770 : if (l_tmp == Tail) {
434 26 : fprintf(stderr,"%s:%d Block not found for deletion\n",__FILE__, __LINE__);
435 26 : return 1;
436 : }
437 :
438 : /* Libération des ressources acquises */
439 : /* On ne libère pas le bloc mémoire lui-même */
440 744 : free(l_tmp->File);
441 744 : free(l_tmp->CompilDate);
442 744 : free(l_tmp->CompilTime);
443 744 : free(l_tmp->Function);
444 :
445 : /* Retrait de la description de la liste (Section critique) */
446 744 : l_tmp->Next->Prev = l_tmp->Prev;
447 744 : l_tmp->Prev->Next = l_tmp->Next;
448 :
449 : /* Mise à jour des compteurs */
450 744 : NbBlocks--;
451 744 : RAMSize -= l_tmp->Size;
452 :
453 : /* Libération de la description */
454 744 : free(l_tmp);
455 :
456 744 : return 0;
457 : }
458 :
459 : /** Dump memory block metadata entries from the list (postinit)
460 : *
461 : * This function is referenced by the memtrack_addblock functor after
462 : * initialization. This is the real implementation of the feature.
463 : *
464 : * \sa memtrack_dumpblocks
465 : * \sa memtrack_dumpblocks_preinit
466 : */
467 690 : static uint64_t memtrack_dumpblocks_postinit() {
468 : TMemBlock *l_tmp;
469 690 : uint64_t l_NbBlocks = 0;;
470 :
471 690 : if (Head->Next != Tail) {
472 : size_t l_BlockSize;
473 321 : fprintf(stderr,
474 : "+----------------------------------------------------------------------------------------------------------+\n");
475 321 : fprintf(stderr, "| %-104s |\n", "Memory Tracker Report");
476 321 : fprintf(stderr,
477 : "+----------------------+----------------------+------+-----------------+----------+------------------------+\n");
478 321 : fprintf(stderr,
479 : "| %-20s | %-20s | %-4s | %-15s | %-8s | %-22s |\n",
480 : "Function", "File", "Line", "Address", "Bytes",
481 : "Compiled");
482 321 : fprintf(stderr,
483 : "+----------------------+----------------------+------+-----------------+----------+------------------------+\n");
484 :
485 321 : l_tmp = Head->Next; /**< Curseur */
486 321 : l_BlockSize = 0;
487 1170 : while (l_tmp != Tail) {
488 849 : fprintf(stderr,
489 : "| %-20s | %-20s | %4d | %15p | %8lu | %11s @ %8s |\n",
490 : l_tmp->Function, l_tmp->File, l_tmp->Line,
491 849 : l_tmp->Ptr, (unsigned long)l_tmp->Size, l_tmp->CompilDate,
492 : l_tmp->CompilTime);
493 849 : l_NbBlocks++;
494 849 : l_BlockSize += l_tmp->Size;
495 849 : l_tmp = l_tmp->Next;
496 : }
497 321 : fprintf(stderr,
498 : "+----------------------+----------------------+------+-----------------+----------+------------------------+\n");
499 321 : fprintf(stderr,
500 : "| %9lu bytes in %6lu blocks. %70s |\n", (unsigned long)l_BlockSize,
501 : (unsigned long)l_NbBlocks, "");
502 321 : fprintf(stderr,
503 : "+----------------------------------------------------------------------------------------------------------+\n");
504 : }
505 : /* Add ASSERT or assert (l_NbBlocks==NbBlocks) */
506 690 : return l_NbBlocks;
507 : }
508 :
509 : /** Get the memory block metadata entries count (postinit)
510 : *
511 : * This function is referenced by the memtrack_addblock functor after
512 : * initialization. This is the real implementation of the feature.
513 : *
514 : * \sa memtrack_getallocatedblocks
515 : * \sa memtrack_getallocatedblocks_preinit
516 : */
517 1930 : static uint64_t memtrack_getallocatedblocks_postinit() {
518 1930 : return NbBlocks;
519 : }
520 :
521 : /** Get the memory block metadata entries total RAM (postinit)
522 : *
523 : * This function is referenced by the memtrack_addblock functor after
524 : * initialization. This is the real implementation of the feature.
525 : *
526 : * \sa memtrack_getallocatedRAM
527 : * \sa memtrack_getallocatedRAM_preinit
528 : */
529 1235 : static uint64_t memtrack_getallocatedRAM_postinit() {
530 1235 : return RAMSize;
531 : }
532 :
533 : /** Get a memory block RAM size (postinit)
534 : *
535 : * This function is referenced by the memtrack_addblock functor after
536 : * initialization. This is the real implementation of the feature.
537 : *
538 : * \sa memtrack_getblocksize
539 : * \sa memtrack_getblocksize_preinit
540 : */
541 904 : static size_t memtrack_getblocksize_postinit(const void *p_Ptr) {
542 : /* Recherche de la description */
543 904 : TMemBlock *l_tmp = Head->Next;
544 2206 : while ((l_tmp->Ptr != p_Ptr) && (l_tmp != Tail))
545 1302 : l_tmp = l_tmp->Next;
546 :
547 : /* Le bloc doit avoir été trouvé */
548 904 : if (l_tmp == Tail)
549 388 : return 0;
550 : else
551 516 : return l_tmp->Size;
552 : }
553 :
554 : /** Functor to register an allocated memory block metadata
555 : *
556 : * Create and adds a memory block metadata record in the tracking system to
557 : * detect memory leaks. It performs some basic sanity checks. The filename,
558 : * compilation date and compilation time can not be null or empty, the line
559 : * number can not be 0, the memory pointer to store can not be NULL or already
560 : * registered and its size needs to be greater than 0.
561 : *
562 : * The function is called from memdbg.c functions used in the application code
563 : * thru memory.h macros. The macro automatically fills the filename, line
564 : * number, compilation date and time, and function name (using GCC's non-ansi
565 : * __func_ extension).
566 : *
567 : * This functor is used to implement a lazy initialization. It initialy
568 : * reference a temporary function to trigger memtrack initialization before
569 : * calling the actual function. Then, it references the actual function directly
570 : * to avoid any useless tests.
571 : *
572 : * @param [in] p_Ptr Allocated memory block pointer
573 : * @param [in] p_Size Allocated memory block size
574 : * @param [in] p_File : Source file
575 : * @param [in] p_Line : Source line number
576 : * @param [in] p_CompilDate : File compilation date
577 : * @param [in] p_CompilTime : File compilation time
578 : * @param [in] p_Function : Source function name
579 : *
580 : * @return Registration status
581 : * @retval 0 if succeeded,
582 : * @retval 1 if not possible.
583 : */
584 : unsigned 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 :
593 : /** Functor to unregister an allocated memory block metadata
594 : *
595 : * Find and delete a memory block metadata record in the tracking system.
596 : * It performs some basic sanity checks. The filename, compilation date and
597 : * compilation time can not be null or empty, the line number can not be 0, the
598 : * memory pointer to remove can not be NULL, it needs to already be registered.
599 : *
600 : * The function is called from memdbg.c functions used in the application code
601 : * thru memory.h macros. The macro automatically fills the filename, line
602 : * number, compilation date and time, and function name (using GCC's non-ansi
603 : * __func_ extension).
604 : *
605 : * This functor is used to implement a lazy initialization. It initialy
606 : * reference a temporary function to trigger memtrack initialization before
607 : * calling the actual function. Then, it references the actual function directly
608 : * to avoid any useless tests.
609 : *
610 : * @param [in] p_Ptr Allocated memory block pointer
611 : * @param [in] p_File : Source file
612 : * @param [in] p_Line : Source line number
613 : * @param [in] p_CompilDate : File compilation date
614 : * @param [in] p_CompilTime : File compilation time
615 : * @param [in] p_Function : Source function name
616 : *
617 : * @return Registration status
618 : * @retval 0 if succeeded,
619 : * @retval !0 if not possible.
620 : */
621 : unsigned 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 :
629 : /** Functor to list allocated memory blocks metadata
630 : *
631 : * Dumps all the metadata of the registered memory blocks to stderr.
632 : *
633 : * This functor is used to implement a lazy initialization. It initialy
634 : * reference a temporary function to trigger memtrack initialization before
635 : * calling the actual function. Then, it references the actual function directly
636 : * to avoid any useless tests.
637 : *
638 : * @return Number of registered blocks (counted)
639 : * @retval 0 if succeeded,
640 : * @retval !0 if not possible.
641 : */
642 : uint64_t (*memtrack_dumpblocks) () = memtrack_dumpblocks_preinit;
643 :
644 : /** Functor to get the number of allocated blocks
645 : *
646 : * This function returns the value of the internal counter of allocated memory
647 : * blocks metadata.
648 : *
649 : * This functor is used to implement a lazy initialization. It initialy
650 : * reference a temporary function to trigger memtrack initialization before
651 : * calling the actual function. Then, it references the actual function directly
652 : * to avoid any useless tests.
653 : *
654 : * @return Number of registered blocks
655 : */
656 : uint64_t (*memtrack_getallocatedblocks) () = memtrack_getallocatedblocks_preinit;
657 :
658 : /** Functor to get the total RAM size allocated
659 : *
660 : * This function returns the internal summ of all the allocated memory blocks
661 : * which are registered.
662 : *
663 : * This functor is used to implement a lazy initialization. It initialy
664 : * reference a temporary function to trigger memtrack initialization before
665 : * calling the actual function. Then, it references the actual function directly
666 : * to avoid any useless tests.
667 : *
668 : * @return Total RAM size in bytes
669 : */
670 : uint64_t (*memtrack_getallocatedRAM) () = memtrack_getallocatedRAM_preinit;
671 :
672 : /** Functor to get size of a specific memory block
673 : *
674 : * The function will search in the list for the specified pointer. If the
675 : * pointer is not found, it will return 0, which is discriminent as the
676 : * memtracker does not allow to track a zero sized block. The memtracker does
677 : * not allow neither to track a NULL pointer, thus NULL will return 0.
678 : * Otherwise, the function will return the memory block size.
679 : *
680 : * This functor is used to implement a lazy initialization. It initialy
681 : * reference a temporary function to trigger memtrack initialization before
682 : * calling the actual function. Then, it references the actual function directly
683 : * to avoid any useless tests.
684 : *
685 : * @param [in] p_Ptr Allocated and tracked memory block pointer
686 : *
687 : * @return Memory block size in bytes
688 : */
689 : size_t(*memtrack_getblocksize) (const void *p_Ptr) = memtrack_getblocksize_preinit;
690 :
691 : /* vim: set tw=80: */
|