LCOV - code coverage report
Current view: top level - deps/debug - memdbg.c (source / functions) Hit Total Coverage
Test: mkernel.info Lines: 53 53 100.0 %
Date: 2024-07-31 10:26:45 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /**         @file  memdbg.c
       2             :  *         @brief  Memory leak tracker 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-07-28 15:35
      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             : #include "memdbg.h"
      20             : #include <string.h> /* memset, memcpy, memmove */
      21             : #include <stdio.h> /* asprintf */
      22             : #include <stdarg.h> /* va_list, va_start, va_arg, va_end */
      23             : 
      24             : /* Documented in header file */
      25        9973 : void* dbg_malloc(
      26             :     const size_t Size,
      27             :     const char* File,
      28             :     const int Line,
      29             :     const char* CompilDate,
      30             :     const char* CompilTime,
      31             :     const char* Function
      32             : )
      33             : {
      34             :     /* Memory allocation */
      35        9973 :     void* l_tmp = malloc(Size);
      36        9973 :     if (NULL == l_tmp) return (l_tmp);
      37             : 
      38             :     /* If successful, track the memory block */
      39             : #pragma GCC diagnostic push                             /* save the actual diag context */
      40             : #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"  /* locally disable maybe warnings */
      41        8921 :     if (0!=memtrack_addblock( l_tmp, Size, File,Line,CompilDate,CompilTime,Function)) {
      42             : #pragma GCC diagnostic pop                              /* restore previous diag context */
      43             :         /* If tracking fails, the whole allocation fails */
      44        1618 :         free(l_tmp);
      45        1618 :         l_tmp = NULL;
      46             :     };
      47             : 
      48        8921 :     return l_tmp;
      49             : }
      50             : 
      51             : /* Documented in header file */
      52        5538 : void dbg_free(
      53             :     void* Ptr,
      54             :     const char* File,
      55             :     const int Line,
      56             :     const char* CompilDate,
      57             :     const char* CompilTime,
      58             :     const char* Function
      59             : )
      60             : {
      61             :     /* If the pointer was not NULL, it was tracked, remove it from the tracked
      62             :      * list. If it was not tracked, removing returns an error. Abort the
      63             :      * process as it should never have an untracked pointer. Either it was
      64             :      * allocated from a non instrumented binary, or it was allocated from
      65             :      * a non monitored function (see memory.h) or there is a bug in the
      66             :      * memory leak tracker. */
      67        5538 :     if (NULL!=Ptr)
      68        4752 :         if (0!=memtrack_delblock(Ptr,File,Line,CompilDate,CompilTime,Function))
      69           8 :             abort();
      70             : 
      71             :     /* If the pointer was NULL or tracked, forward it to the real free */
      72        5530 :     free(Ptr);
      73        5530 : }
      74             : 
      75             : /* Documented in header file */
      76         924 : void* dbg_calloc(
      77             :     const size_t NMemb,
      78             :     const size_t Size,
      79             :     const char* File,
      80             :     const int Line,
      81             :     const char* CompilDate,
      82             :     const char* CompilTime,
      83             :     const char* Function
      84             : )
      85             : {
      86             :     void* l_tmp;
      87             : 
      88             :     /* Use the dbg_malloc function to allocate the memory */
      89         924 :     l_tmp = dbg_malloc(
      90             :                 NMemb*Size,
      91             :                 File,Line,CompilDate,CompilTime,Function);
      92             : 
      93             :     /* Implement the calloc specific behavior compared to simple malloc:
      94             :      * it fills the allocated memory block with 0 */
      95         924 :     if (NULL != l_tmp)
      96          18 :         memset((char*)l_tmp, 0, NMemb*Size);
      97             : 
      98         924 :     return l_tmp;
      99             : }
     100             : 
     101             : /* Documented in header file */
     102        1558 : void* dbg_realloc(
     103             :     void* Ptr,
     104             :     const size_t Size,
     105             :     const char* File,
     106             :     const int Line,
     107             :     const char* CompilDate,
     108             :     const char* CompilTime,
     109             :     const char* Function
     110             : )
     111             : {
     112             :     size_t l_oldsize; /**< Existing bloc size */
     113             :     char *newblk;                               /**< New block */
     114             : 
     115             :     /* NULL is not tracked but valid */
     116        1558 :     if (NULL==Ptr) {
     117         450 :         l_oldsize=0;
     118             :     } else {
     119             :         /* Fetch existing block size */
     120        1108 :         l_oldsize = memtrack_getblocksize(Ptr);
     121             : 
     122             :         /* This is probably a bug in the memory tracker.
     123             :          * It should not track zero sized blocks */
     124        1108 :         if (0==l_oldsize)
     125          16 :             abort();
     126             :     }
     127             : 
     128             :     /* If new size is 0, then act as free, like realloc */
     129        1542 :     if (0==Size) {
     130         198 :         dbg_free(Ptr,
     131             :                  File,Line,CompilDate,CompilTime,Function
     132             :                 );
     133         198 :         return Ptr;
     134             :     }
     135             : 
     136             :     /* New sized block allocation to simulate the worst case scenario and
     137             :      * test a pointer change, a data loss (in case of shrink) */
     138        1344 :     newblk=(char*)dbg_malloc(
     139             :                Size,
     140             :                File,Line,CompilDate,CompilTime,Function
     141             :            );
     142             :     /* The new block can fail */
     143             :     /* The real realloc function could succeed here, in case of inplace
     144             :      * shrink in an OOM situation. */
     145        1344 :     if (NULL == newblk) return (newblk);
     146             : 
     147             :     /* Copy only the relevant data from old block to new block, loosing extra
     148             :      * data in case of shrink, and not initializing new data in case of
     149             :      * increase */
     150         414 :     memcpy(newblk,(char*)Ptr,(l_oldsize<Size?l_oldsize:Size));
     151             : 
     152             :     /* Free old block */
     153         414 :     dbg_free(
     154             :         Ptr,
     155             :         File,Line,CompilDate,CompilTime,Function
     156             :     );
     157             : 
     158         414 :     return (void*) newblk;
     159             : }
     160             : 
     161             : 
     162             : /* Documented in header file */
     163        1803 : char* dbg_strdup(
     164             :     const char* Ptr,
     165             :     const char* File,
     166             :     const int Line,
     167             :     const char* CompilDate,
     168             :     const char* CompilTime,
     169             :     const char* Function
     170             : )
     171             : {
     172             :     char* l_newblk;                             /** Copy address */
     173             : 
     174             :     /* Use strdup to actually copy the string with its own return values and
     175             :      * abort (SIGSEGV in case of NULL) */
     176        1803 :     l_newblk=NULL;
     177        1803 :     l_newblk=strdup(Ptr);
     178             : 
     179             :     /* If the copy succeeded, try to track the memory allocation */
     180        1791 :     if (NULL != l_newblk)
     181        1360 :         if (0!=memtrack_addblock(
     182             :                 l_newblk,
     183        1360 :                 strlen(l_newblk)+1,
     184             :                 File,Line,CompilDate,CompilTime,Function
     185             :             )) {
     186             :             /* If tracking fails, the whole operation is reverted and fails */
     187        1270 :             free(l_newblk);
     188        1270 :             l_newblk=NULL;
     189             :         };
     190             : 
     191        1791 :     return l_newblk;
     192             : }
     193             : 
     194             : 
     195             : /* Documented in header file */
     196        1060 : int dbg_asprintf(char **p_Ptr,
     197             :                  const char* p_Format,
     198             :                  const char *File,
     199             :                  const int Line,
     200             :                  const char *CompilDate,
     201             :                  const char *CompilTime, const char *Function,
     202             :                  ...)
     203             : {
     204             :     int l_returncode;
     205             : 
     206             :     /* NULL is not allowed, where would we store the result, then ? */
     207        1060 :     if(NULL==p_Ptr)
     208           4 :         abort();
     209             : 
     210             :     /* Limit the scope of the variadic manipulation variables */
     211             :     {
     212             :         va_list l_ap;
     213        1056 :         va_start (l_ap, Function);
     214             :         /* Use the original vasprintf to build the formatted string */
     215             :         /** @todo Implement a vasprintf wrapping function to catch allocation
     216             :          * and use it here */
     217        1056 :         l_returncode = vasprintf(p_Ptr, p_Format, l_ap);
     218        1056 :         va_end(l_ap);
     219             :     }
     220             : 
     221             :     /* If formatting succeeded, try to track the memory allocation */
     222        1056 :     if (-1 != l_returncode)
     223         558 :         if (1==memtrack_addblock(
     224             :                 *p_Ptr,
     225         558 :                 strlen (*p_Ptr)+1,
     226             :                 File,Line,CompilDate,CompilTime,Function
     227             :             )) {
     228             :             /* If tracking fails, the whole operation is reverted and fails */
     229         528 :             free(*p_Ptr);
     230         528 :             l_returncode=-2;
     231             :         };
     232             : 
     233        1056 :     return l_returncode;
     234             : }
     235             : 

Generated by: LCOV version 1.16