home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / lang / c / 17039 < prev    next >
Encoding:
Text File  |  1992-11-23  |  10.5 KB  |  369 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!usc!cs.utexas.edu!sdd.hp.com!saimiri.primate.wisc.edu!usenet.coe.montana.edu!news.u.washington.edu!uw-beaver!newsfeed.rice.edu!rice!abuhr
  3. From: abuhr@owlnet.rice.edu (Aaron M. Buhr)
  4. Subject: Re: Help me track down memory leakage
  5. Message-ID: <By6G98.68L@rice.edu>
  6. Sender: news@rice.edu (News)
  7. Organization: Rice University
  8. References: <BxuLIr.DK@rice.edu> <1992Nov19.161411.25199@titan.inmos.co.uk>
  9. Date: Mon, 23 Nov 1992 16:24:43 GMT
  10. Lines: 357
  11.  
  12.  
  13.       Thanks to all who responded to my earlier post about helping me
  14. track down the memory leak.  Most of the respondents said to either
  15. acquire a commercial product such as Purify, use one of the freely
  16. available routines, or make my own.  Since the Purify product is
  17. priced in the thousands of dollars it's out of my price range.  The
  18. only standard free memory allocation debugging product seemed to be
  19. the malloc_debug routines available on some Suns.  I decided to make
  20. my own routines, both so that I could customize it to fit my uses and
  21. because I thought I might be able to create my own faster than I could
  22. track down, learn, and integrate someone else's routine.
  23.  
  24.      As it turns out, I am having a strange error that I cannot figure
  25. out.  The dbg_malloc and dbg_free routines seem to be working fine, in
  26. that they return pointers to valid-sized memory blocks and free those
  27. memory blocks, and it seems that those blocks can be manipulated
  28. directly or by some library calls (strcpy for example).  However, for
  29. some reason sscanf() returns a bus error when I try to use it on one
  30. of the blocks the dbg_malloc() routines returned (the sscanf() works
  31. fine with the regular C library malloc() routine).  Here's the gdb
  32. output:
  33.  
  34. /* error: */
  35. Program received signal 10, Bus error
  36. 0xf773cb80 in _doscan ()
  37.  
  38. /* I made a breakpoint before the fatal call below, and single stepped
  39. up to it: */
  40. 484                                             CREATE(index, struct index_data,
  41.  numentries);   /* this calls dbg_calloc(index, sizeof(struct */
  42.                 /* index_data) * numentries) */
  43. (gdb)
  44. 497                                     sscanf(buf, "#%d", &index[i].virtual);
  45. (gdb) p index
  46. $1 = (struct index_data *) 0xd8129   /* memory was allocated properly */
  47. (gdb) p *index
  48. $2 = {virtual = 0, name = 0x0, pos = 0, number = 0, func = 0, easyActs = 0x0,
  49.   easyActFlags = 0, group = 0}
  50. (gdb) p (char *) 0xd8109
  51. $3 = 0xd8109 "b.c"
  52. (gdb) p (char *) 0xd8108
  53. $4 = 0xd8108 "db.c"            /* the filename seems to have been */
  54. (gdb) p (int *) 0xd811c           /* properly inserted into the debug */ 
  55. $5 = (int *) 0xd811c           /* block at the beginning of the */
  56. (gdb) p *((int *) 0xd811c)     /* allocated memory block */
  57. $6 = 14942208
  58. (gdb) n
  59.  
  60. Program received signal 10, Bus error
  61. 0xf773cb80 in _doscan ()
  62.  
  63. /* another run: */
  64. Continuing.
  65.  
  66. Breakpoint 4, generate_indices (fl=0xf77a201c, top=0xb852c) at db.c:497
  67. 497                                     sscanf(buf, "#%d", &index[i].virtual);
  68. (gdb) p index[i].virtual   /* can view allocated mem */
  69. $10 = 0
  70. (gdb) p &index[i].virtual  
  71. $11 = (int *) 0xd8129
  72. (gdb) p i
  73. $12 = 0
  74. (gdb) set index[i].virtual = 1   /* can manipulate allocated mem directly */
  75. (gdb) p index[i].virtual
  76. $13 = 1
  77. (gdb) p index
  78. $14 = (struct index_data *) 0xd8129
  79. (gdb) n
  80.  
  81. /* but won't work with sscanf() : */
  82. Program received signal 10, Bus error   
  83. 0xf773cb80 in _doscan ()
  84.  
  85.  
  86.  
  87.     Below are the C routines to handle everything.  I'm releasing them
  88. into the public domain.  Use them however you wish.
  89.  
  90.  
  91. /* dbg_malloc.h - memory allocation routines with embedded debugging info */
  92. /* by Aaron Buhr (abuhr@owlnet.rice.edu) */
  93.  
  94. #ifndef DBG_MALLOC
  95.  
  96. #define PTR_TYPE void *
  97.  
  98.  
  99. PTR_TYPE dbg_malloc (char *sourcefilename, int sourceline, unsigned size);
  100. PTR_TYPE dbg_calloc (char *sourcefilename, int sourceline,
  101.              unsigned number, unsigned size_each);
  102. void dbg_free (char *sourcefilename, int sourceline, void *mem);
  103. PTR_TYPE dbg_realloc (char *sourcefilename, int sourceline,
  104.               PTR_TYPE mem, unsigned size);
  105. int Log_Mem_Status(char *mem_file_name);
  106.  
  107. #define malloc(size) dbg_malloc(__FILE__, __LINE__, size)
  108. #define calloc(num, size_each) dbg_calloc(__FILE__, __LINE__, num, size_each)
  109. #define free(memptr) dbg_free(__FILE__, __LINE__, memptr)
  110. #define realloc(memptr, size) dbg_realloc(__FILE__, __LINE__, memptr, size)
  111.  
  112.  
  113. #define DBG_MALLOC
  114.  
  115. #endif
  116.  
  117. /* end dbg_malloc.h */
  118.  
  119.  
  120.  
  121. /* dbg_malloc.c - memory allocation routines with embedded debugging info */
  122. /* by Aaron Buhr (abuhr@owlnet.rice.edu) */
  123.  
  124. #ifdef malloc
  125. #undef malloc
  126. #endif
  127. #ifdef calloc
  128. #undef calloc
  129. #endif
  130. #ifdef free
  131. #undef free
  132. #endif
  133. #ifdef realloc
  134. #undef realloc
  135. #endif
  136.  
  137. #include <stdio.h>
  138. #include <stdlib.h>
  139. #include <string.h>
  140. #include <malloc.h>
  141. #include <memory.h>
  142. #include <sys/time.h>
  143. #include "dbg_malloc.h"
  144.  
  145.  
  146. #define FNAME_SIZE 20
  147. #define GET_SFNAME(memptr) ((char *) (memptr))
  148. #define GET_SLINE(memptr) ((int) (*( (((char *) memptr) + FNAME_SIZE + 1))))
  149. #define GET_SIZE(memptr) ((unsigned) (*( (((char *) memptr) + FNAME_SIZE \
  150.                         + 1 + sizeof(int)))))
  151. #define GET_TIME(memptr) ((time_t) (*( (((char *) memptr) + FNAME_SIZE \
  152.                       + 1 + sizeof(int) \
  153.                       + sizeof(unsigned) ))))
  154. #define DEBUG_BLOCK_SIZE (FNAME_SIZE + 1 + sizeof(int) + sizeof(unsigned) \
  155.               + sizeof(time_t))
  156.  
  157.  
  158. struct ptr_node_struct {
  159.     PTR_TYPE mem_ptr;
  160.     struct ptr_node_struct *next;
  161. };
  162.  
  163.  
  164. struct mem_realloc_struct {
  165.     PTR_TYPE mem_ptr;
  166.     char *sourcefilename;
  167.     int sourceline;
  168.     unsigned old_size;
  169.     unsigned new_size;
  170.     time_t realloc_time;
  171.     struct mem_realloc_struct *next;
  172. };
  173.  
  174. struct ptr_node_struct *allocd_mem = 0;
  175. struct mem_realloc_struct *reallocd_mem = 0;
  176.  
  177.  
  178. PTR_TYPE dbg_malloc (char *sourcefilename, int sourceline, unsigned size) {
  179.  
  180.     unsigned new_size;
  181.     PTR_TYPE new_mem;
  182.     struct ptr_node_struct *node;
  183.  
  184.     new_size = size + DEBUG_BLOCK_SIZE;
  185.     new_mem = malloc(new_size);
  186.     if (!new_mem) return 0;
  187.     if (!(node = malloc(sizeof(struct ptr_node_struct)))) {
  188.     /* not enough mem to allocate mem tracking node */
  189.     free(new_mem);
  190.     return 0;
  191.     }
  192.  
  193.     strncpy(GET_SFNAME(new_mem), sourcefilename, FNAME_SIZE + 1);
  194.     ((char *) new_mem)[FNAME_SIZE] = 0;
  195.     GET_SLINE(new_mem) = sourceline; 
  196.     
  197.     GET_SIZE(new_mem) = size;
  198.     GET_TIME(new_mem) = time(0);
  199.     
  200.     node->mem_ptr = (PTR_TYPE) (new_mem + DEBUG_BLOCK_SIZE);
  201.     node->next = allocd_mem;
  202.     allocd_mem = node;
  203.     return ( (PTR_TYPE) (new_mem + DEBUG_BLOCK_SIZE));
  204. }
  205.  
  206.  
  207.  
  208.  
  209. PTR_TYPE dbg_calloc (char *sourcefilename, int sourceline,
  210.              unsigned number, unsigned size_each) {
  211.  
  212.     PTR_TYPE *temp;
  213.  
  214.     temp = dbg_malloc(sourcefilename, sourceline, number * size_each);
  215.     if (temp)
  216.       memset(temp, 0, number * size_each);
  217.     return temp;
  218. }
  219.     
  220.  
  221.  
  222. void dbg_free (char *sourcefilename, int sourceline, void *mem) {
  223.  
  224.     register struct ptr_node_struct *node, *last;
  225.     
  226.     for (last = 0, node = allocd_mem; node; last = node, node = node->next)
  227.       if (node->mem_ptr == mem) {
  228.       if (!last) {
  229.           allocd_mem = node->next;
  230.       } else {
  231.           last->next = node->next;
  232.       }
  233.       free(node);
  234.       
  235.       mem = (char *) (mem - DEBUG_BLOCK_SIZE);
  236.       free(mem);
  237.  
  238.       break;
  239.       }
  240.  
  241.     /* maybe put a log message here that user tried to free memory
  242.        that we don't believe was allocated */
  243.     return;
  244. }
  245.               
  246.  
  247.  
  248.  
  249. PTR_TYPE dbg_realloc (char *sourcefilename, int sourceline,
  250.           PTR_TYPE mem, unsigned size) {
  251.  
  252.     register struct ptr_node_struct *node, *last, *found = 0;
  253.     struct mem_realloc_struct *realloc_node;
  254.     PTR_TYPE real_mem_ptr;
  255.     
  256.  
  257.     for (last = 0, node = allocd_mem;
  258.      (node) && (!found);
  259.      last = node, node = node->next)
  260.       if (node->mem_ptr == mem) found = node;
  261.  
  262.     if (found) {
  263.     if (!(realloc_node = malloc(sizeof(struct mem_realloc_struct)))) {
  264.         /* couldn't make new realloc node */
  265.         return 0;
  266.     }
  267.  
  268.     real_mem_ptr = (PTR_TYPE) (found->mem_ptr - DEBUG_BLOCK_SIZE);
  269.     realloc_node->mem_ptr = found->mem_ptr;
  270.     realloc_node->sourcefilename = strdup(sourcefilename);
  271.     realloc_node->sourceline = sourceline;
  272.     realloc_node->old_size = GET_SIZE(real_mem_ptr);
  273.     realloc_node->new_size = size;
  274.     realloc_node->realloc_time = time(0);
  275.     realloc_node->next = reallocd_mem;
  276.     reallocd_mem = realloc_node;
  277.  
  278.     found->mem_ptr = realloc(real_mem_ptr, size + DEBUG_BLOCK_SIZE)
  279.       + DEBUG_BLOCK_SIZE;
  280.     return(found->mem_ptr);
  281.     }
  282.  
  283.     /* maybe put a log message here that user tried to realloc memory
  284.        that we don't believe was allocated */
  285.     return;
  286. }
  287.  
  288.  
  289. static char *DM_Time_Str(struct tm *timeStruct, char *tmstr) {
  290.         char daystr[3];
  291.  
  292.         switch (timeStruct->tm_wday) {
  293.                 case 0:  strcpy(daystr,"Su"); break;
  294.                 case 1:  strcpy(daystr,"Mo"); break;
  295.                 case 2:  strcpy(daystr,"Tu"); break;
  296.                 case 3:  strcpy(daystr,"We"); break;
  297.                 case 4:  strcpy(daystr,"Th"); break;
  298.                 case 5:  strcpy(daystr,"Fr"); break;
  299.                 case 6:  strcpy(daystr,"Sa"); break;
  300.                 default: strcpy(daystr,"FU"); break;
  301.         }
  302.  
  303.         sprintf(tmstr,"%s %d/%d %2d:%.2d",daystr,timeStruct->tm_mon+1,timeStruc\
  304. t->tm_mday,timeStruct->tm_hour,timeStruct->tm_min);
  305.         return tmstr;
  306. }
  307.  
  308.  
  309.  
  310.  
  311. int Log_Mem_Status(char *mem_file_name) {
  312.  
  313.     FILE *mem_file;
  314.     char buf1[120];
  315.     struct ptr_node_struct *node;
  316.     PTR_TYPE real_ptr;
  317.     struct mem_realloc_struct *realloc_node;
  318.     
  319.  
  320.     if (!(mem_file = fopen(mem_file_name, "w"))) return -1;
  321.  
  322.     fprintf(mem_file, "Memory allocations:\n");
  323.     for (node = allocd_mem; node; node = node->next) {
  324.     real_ptr = node->mem_ptr - DEBUG_BLOCK_SIZE;
  325.     fprintf(mem_file, "%s: %20.20s -5.5i: %db @ 0x%X\n",
  326.         DM_Time_Str(localtime(GET_TIME(real_ptr)), buf1),
  327.         GET_SFNAME(real_ptr),
  328.         GET_SLINE(real_ptr),
  329.         GET_SIZE(real_ptr),
  330.         node->mem_ptr);
  331.     }
  332.  
  333.     fprintf(mem_file, "\n\n");
  334.     
  335.     fprintf(mem_file, "Memory reallocations:\n");
  336.     for (realloc_node = reallocd_mem;
  337.      realloc_node; realloc_node = realloc_node->next) {
  338.     real_ptr = realloc_node->mem_ptr - DEBUG_BLOCK_SIZE;
  339.     fprintf(mem_file, "%s: %20.20s -5.5i: %db @ 0x%X -> %db\n",
  340.         DM_Time_Str(localtime(realloc_node->realloc_time), buf1),
  341.         realloc_node->sourcefilename,
  342.         realloc_node->sourceline,
  343.         realloc_node->old_size,
  344.         realloc_node->mem_ptr,
  345.         realloc_node->new_size);
  346.     }
  347.     fclose(mem_file);
  348.     return 0;
  349. }
  350.         
  351.         
  352.  
  353. #define malloc(size) dbg_malloc(__FILE__, __LINE__, size)
  354. #define calloc(num, size_each) dbg_calloc(__FILE__, __LINE__, num, size_each)
  355. #define free(memptr) dbg_free(__FILE__, __LINE__, memptr)
  356. #define realloc(memptr, size) dbg_realloc(__FILE__, __LINE__, memptr, size)
  357.  
  358. /* end dbg_malloc.c */
  359.  
  360.  
  361.  
  362.      Thanks again to all who responded to my previous message, and
  363. thanks in advance for help on this one.
  364.  
  365.  
  366. Aaron Buhr
  367. abuhr@owlnet.rice.edu
  368.  
  369.