home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c
- 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
- From: abuhr@owlnet.rice.edu (Aaron M. Buhr)
- Subject: Re: Help me track down memory leakage
- Message-ID: <By6G98.68L@rice.edu>
- Sender: news@rice.edu (News)
- Organization: Rice University
- References: <BxuLIr.DK@rice.edu> <1992Nov19.161411.25199@titan.inmos.co.uk>
- Date: Mon, 23 Nov 1992 16:24:43 GMT
- Lines: 357
-
-
- Thanks to all who responded to my earlier post about helping me
- track down the memory leak. Most of the respondents said to either
- acquire a commercial product such as Purify, use one of the freely
- available routines, or make my own. Since the Purify product is
- priced in the thousands of dollars it's out of my price range. The
- only standard free memory allocation debugging product seemed to be
- the malloc_debug routines available on some Suns. I decided to make
- my own routines, both so that I could customize it to fit my uses and
- because I thought I might be able to create my own faster than I could
- track down, learn, and integrate someone else's routine.
-
- As it turns out, I am having a strange error that I cannot figure
- out. The dbg_malloc and dbg_free routines seem to be working fine, in
- that they return pointers to valid-sized memory blocks and free those
- memory blocks, and it seems that those blocks can be manipulated
- directly or by some library calls (strcpy for example). However, for
- some reason sscanf() returns a bus error when I try to use it on one
- of the blocks the dbg_malloc() routines returned (the sscanf() works
- fine with the regular C library malloc() routine). Here's the gdb
- output:
-
- /* error: */
- Program received signal 10, Bus error
- 0xf773cb80 in _doscan ()
-
- /* I made a breakpoint before the fatal call below, and single stepped
- up to it: */
- 484 CREATE(index, struct index_data,
- numentries); /* this calls dbg_calloc(index, sizeof(struct */
- /* index_data) * numentries) */
- (gdb)
- 497 sscanf(buf, "#%d", &index[i].virtual);
- (gdb) p index
- $1 = (struct index_data *) 0xd8129 /* memory was allocated properly */
- (gdb) p *index
- $2 = {virtual = 0, name = 0x0, pos = 0, number = 0, func = 0, easyActs = 0x0,
- easyActFlags = 0, group = 0}
- (gdb) p (char *) 0xd8109
- $3 = 0xd8109 "b.c"
- (gdb) p (char *) 0xd8108
- $4 = 0xd8108 "db.c" /* the filename seems to have been */
- (gdb) p (int *) 0xd811c /* properly inserted into the debug */
- $5 = (int *) 0xd811c /* block at the beginning of the */
- (gdb) p *((int *) 0xd811c) /* allocated memory block */
- $6 = 14942208
- (gdb) n
-
- Program received signal 10, Bus error
- 0xf773cb80 in _doscan ()
-
- /* another run: */
- Continuing.
-
- Breakpoint 4, generate_indices (fl=0xf77a201c, top=0xb852c) at db.c:497
- 497 sscanf(buf, "#%d", &index[i].virtual);
- (gdb) p index[i].virtual /* can view allocated mem */
- $10 = 0
- (gdb) p &index[i].virtual
- $11 = (int *) 0xd8129
- (gdb) p i
- $12 = 0
- (gdb) set index[i].virtual = 1 /* can manipulate allocated mem directly */
- (gdb) p index[i].virtual
- $13 = 1
- (gdb) p index
- $14 = (struct index_data *) 0xd8129
- (gdb) n
-
- /* but won't work with sscanf() : */
- Program received signal 10, Bus error
- 0xf773cb80 in _doscan ()
-
-
-
- Below are the C routines to handle everything. I'm releasing them
- into the public domain. Use them however you wish.
-
-
- /* dbg_malloc.h - memory allocation routines with embedded debugging info */
- /* by Aaron Buhr (abuhr@owlnet.rice.edu) */
-
- #ifndef DBG_MALLOC
-
- #define PTR_TYPE void *
-
-
- PTR_TYPE dbg_malloc (char *sourcefilename, int sourceline, unsigned size);
- PTR_TYPE dbg_calloc (char *sourcefilename, int sourceline,
- unsigned number, unsigned size_each);
- void dbg_free (char *sourcefilename, int sourceline, void *mem);
- PTR_TYPE dbg_realloc (char *sourcefilename, int sourceline,
- PTR_TYPE mem, unsigned size);
- int Log_Mem_Status(char *mem_file_name);
-
- #define malloc(size) dbg_malloc(__FILE__, __LINE__, size)
- #define calloc(num, size_each) dbg_calloc(__FILE__, __LINE__, num, size_each)
- #define free(memptr) dbg_free(__FILE__, __LINE__, memptr)
- #define realloc(memptr, size) dbg_realloc(__FILE__, __LINE__, memptr, size)
-
-
- #define DBG_MALLOC
-
- #endif
-
- /* end dbg_malloc.h */
-
-
-
- /* dbg_malloc.c - memory allocation routines with embedded debugging info */
- /* by Aaron Buhr (abuhr@owlnet.rice.edu) */
-
- #ifdef malloc
- #undef malloc
- #endif
- #ifdef calloc
- #undef calloc
- #endif
- #ifdef free
- #undef free
- #endif
- #ifdef realloc
- #undef realloc
- #endif
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <malloc.h>
- #include <memory.h>
- #include <sys/time.h>
- #include "dbg_malloc.h"
-
-
- #define FNAME_SIZE 20
- #define GET_SFNAME(memptr) ((char *) (memptr))
- #define GET_SLINE(memptr) ((int) (*( (((char *) memptr) + FNAME_SIZE + 1))))
- #define GET_SIZE(memptr) ((unsigned) (*( (((char *) memptr) + FNAME_SIZE \
- + 1 + sizeof(int)))))
- #define GET_TIME(memptr) ((time_t) (*( (((char *) memptr) + FNAME_SIZE \
- + 1 + sizeof(int) \
- + sizeof(unsigned) ))))
- #define DEBUG_BLOCK_SIZE (FNAME_SIZE + 1 + sizeof(int) + sizeof(unsigned) \
- + sizeof(time_t))
-
-
- struct ptr_node_struct {
- PTR_TYPE mem_ptr;
- struct ptr_node_struct *next;
- };
-
-
- struct mem_realloc_struct {
- PTR_TYPE mem_ptr;
- char *sourcefilename;
- int sourceline;
- unsigned old_size;
- unsigned new_size;
- time_t realloc_time;
- struct mem_realloc_struct *next;
- };
-
- struct ptr_node_struct *allocd_mem = 0;
- struct mem_realloc_struct *reallocd_mem = 0;
-
-
- PTR_TYPE dbg_malloc (char *sourcefilename, int sourceline, unsigned size) {
-
- unsigned new_size;
- PTR_TYPE new_mem;
- struct ptr_node_struct *node;
-
- new_size = size + DEBUG_BLOCK_SIZE;
- new_mem = malloc(new_size);
- if (!new_mem) return 0;
- if (!(node = malloc(sizeof(struct ptr_node_struct)))) {
- /* not enough mem to allocate mem tracking node */
- free(new_mem);
- return 0;
- }
-
- strncpy(GET_SFNAME(new_mem), sourcefilename, FNAME_SIZE + 1);
- ((char *) new_mem)[FNAME_SIZE] = 0;
- GET_SLINE(new_mem) = sourceline;
-
- GET_SIZE(new_mem) = size;
- GET_TIME(new_mem) = time(0);
-
- node->mem_ptr = (PTR_TYPE) (new_mem + DEBUG_BLOCK_SIZE);
- node->next = allocd_mem;
- allocd_mem = node;
- return ( (PTR_TYPE) (new_mem + DEBUG_BLOCK_SIZE));
- }
-
-
-
-
- PTR_TYPE dbg_calloc (char *sourcefilename, int sourceline,
- unsigned number, unsigned size_each) {
-
- PTR_TYPE *temp;
-
- temp = dbg_malloc(sourcefilename, sourceline, number * size_each);
- if (temp)
- memset(temp, 0, number * size_each);
- return temp;
- }
-
-
-
- void dbg_free (char *sourcefilename, int sourceline, void *mem) {
-
- register struct ptr_node_struct *node, *last;
-
- for (last = 0, node = allocd_mem; node; last = node, node = node->next)
- if (node->mem_ptr == mem) {
- if (!last) {
- allocd_mem = node->next;
- } else {
- last->next = node->next;
- }
- free(node);
-
- mem = (char *) (mem - DEBUG_BLOCK_SIZE);
- free(mem);
-
- break;
- }
-
- /* maybe put a log message here that user tried to free memory
- that we don't believe was allocated */
- return;
- }
-
-
-
-
- PTR_TYPE dbg_realloc (char *sourcefilename, int sourceline,
- PTR_TYPE mem, unsigned size) {
-
- register struct ptr_node_struct *node, *last, *found = 0;
- struct mem_realloc_struct *realloc_node;
- PTR_TYPE real_mem_ptr;
-
-
- for (last = 0, node = allocd_mem;
- (node) && (!found);
- last = node, node = node->next)
- if (node->mem_ptr == mem) found = node;
-
- if (found) {
- if (!(realloc_node = malloc(sizeof(struct mem_realloc_struct)))) {
- /* couldn't make new realloc node */
- return 0;
- }
-
- real_mem_ptr = (PTR_TYPE) (found->mem_ptr - DEBUG_BLOCK_SIZE);
- realloc_node->mem_ptr = found->mem_ptr;
- realloc_node->sourcefilename = strdup(sourcefilename);
- realloc_node->sourceline = sourceline;
- realloc_node->old_size = GET_SIZE(real_mem_ptr);
- realloc_node->new_size = size;
- realloc_node->realloc_time = time(0);
- realloc_node->next = reallocd_mem;
- reallocd_mem = realloc_node;
-
- found->mem_ptr = realloc(real_mem_ptr, size + DEBUG_BLOCK_SIZE)
- + DEBUG_BLOCK_SIZE;
- return(found->mem_ptr);
- }
-
- /* maybe put a log message here that user tried to realloc memory
- that we don't believe was allocated */
- return;
- }
-
-
- static char *DM_Time_Str(struct tm *timeStruct, char *tmstr) {
- char daystr[3];
-
- switch (timeStruct->tm_wday) {
- case 0: strcpy(daystr,"Su"); break;
- case 1: strcpy(daystr,"Mo"); break;
- case 2: strcpy(daystr,"Tu"); break;
- case 3: strcpy(daystr,"We"); break;
- case 4: strcpy(daystr,"Th"); break;
- case 5: strcpy(daystr,"Fr"); break;
- case 6: strcpy(daystr,"Sa"); break;
- default: strcpy(daystr,"FU"); break;
- }
-
- sprintf(tmstr,"%s %d/%d %2d:%.2d",daystr,timeStruct->tm_mon+1,timeStruc\
- t->tm_mday,timeStruct->tm_hour,timeStruct->tm_min);
- return tmstr;
- }
-
-
-
-
- int Log_Mem_Status(char *mem_file_name) {
-
- FILE *mem_file;
- char buf1[120];
- struct ptr_node_struct *node;
- PTR_TYPE real_ptr;
- struct mem_realloc_struct *realloc_node;
-
-
- if (!(mem_file = fopen(mem_file_name, "w"))) return -1;
-
- fprintf(mem_file, "Memory allocations:\n");
- for (node = allocd_mem; node; node = node->next) {
- real_ptr = node->mem_ptr - DEBUG_BLOCK_SIZE;
- fprintf(mem_file, "%s: %20.20s -5.5i: %db @ 0x%X\n",
- DM_Time_Str(localtime(GET_TIME(real_ptr)), buf1),
- GET_SFNAME(real_ptr),
- GET_SLINE(real_ptr),
- GET_SIZE(real_ptr),
- node->mem_ptr);
- }
-
- fprintf(mem_file, "\n\n");
-
- fprintf(mem_file, "Memory reallocations:\n");
- for (realloc_node = reallocd_mem;
- realloc_node; realloc_node = realloc_node->next) {
- real_ptr = realloc_node->mem_ptr - DEBUG_BLOCK_SIZE;
- fprintf(mem_file, "%s: %20.20s -5.5i: %db @ 0x%X -> %db\n",
- DM_Time_Str(localtime(realloc_node->realloc_time), buf1),
- realloc_node->sourcefilename,
- realloc_node->sourceline,
- realloc_node->old_size,
- realloc_node->mem_ptr,
- realloc_node->new_size);
- }
- fclose(mem_file);
- return 0;
- }
-
-
-
- #define malloc(size) dbg_malloc(__FILE__, __LINE__, size)
- #define calloc(num, size_each) dbg_calloc(__FILE__, __LINE__, num, size_each)
- #define free(memptr) dbg_free(__FILE__, __LINE__, memptr)
- #define realloc(memptr, size) dbg_realloc(__FILE__, __LINE__, memptr, size)
-
- /* end dbg_malloc.c */
-
-
-
- Thanks again to all who responded to my previous message, and
- thanks in advance for help on this one.
-
-
- Aaron Buhr
- abuhr@owlnet.rice.edu
-
-