Thread: Tracking memory in malloc/free.

  1. #1
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677

    Tracking memory in malloc/free.

    Here's a little project I hacked up that shows how you can track memory allocations by using a macro to replace malloc() & free() with your own function, and using a linked list to store the allocations.

    A note on portability (to avoid some pedant pointing it out later):
    It does use some trickery to find the original pointer - it is not 100% portable, but all compilers I've ever used [which is a reasonable selection of the most popular ones and a few less common ones] allow using negative indices to pointers to "walk backwards" in memory. It could be done more portable by casting pointers to char * and adding/subtracting the sizeof(struct memblk).

    trackmalloc.h:
    Code:
    #ifndef TRACK_MALLOC_H
    #define TRACK_MALLOC_H
    
    #ifndef INTERNAL
    #define malloc(size) trackmalloc(size, #size, __FILE__, __LINE__)
    #define free(ptr) trackfree(ptr, #ptr, __FILE__, __LINE__)
    #endif
    
    void *trackmalloc(size_t size, const char *expr, const char *file, int line);
    void  trackfree(void *ptr, const char *expr, const char *file, int line);
    void trackListAllocations();
    
    
    #endif
    trackmalloc.c:
    Code:
    #define INTERNAL
    #include "trackmalloc.h"
    #include <stdlib.h>
    #include <stdio.h>
    
    
    struct memblk
    {
    	long           magic;
    	struct memblk *next;
    	struct memblk *prev;
    	size_t         size;
    	const char    *file;
    	const char    *expr;
    	int            line;
    	int            padding;   // Make it an even 16 byte length (total size=32 bytes in 32-bit mode). 
    };
    
    #define MAGIC1 0x12345678
    #define MAGIC2 0x87654321
    
    struct memblk *memblockList = NULL;
    
    static void trackMBDetails(struct memblk *mb)
    {
    	printf("%d bytes allocated with \"%s\" at %s:%d\n", mb->size, mb->expr, mb->file, mb->line);
    }
    
    void *trackmalloc(size_t size, const char *expr, const char *file, int line)
    {
        struct memblk *mb = malloc(size + sizeof(*mb));
        if (!mb)
    	{
            // May want to output some error message here!
           return NULL;
    	}
        mb->magic = MAGIC1;
        mb->file = file;
        mb->line = line;
    	mb->expr = expr;
    	mb->size = size;
        mb->prev = NULL;
    	mb->next = memblockList;
    	if (memblockList)
    	{
    		memblockList->prev = mb;
    	}
    	memblockList = mb;
        return (void *)&mb[1];  
    }
    
    
    void  trackfree(void *ptr, const char *expr, const char *file, int line)
    {
        if (!ptr)
           return;
        else
        {
            struct memblk *mb = &((struct memblk *)(ptr))[-1];
            if (mb->magic != MAGIC1)
            { 
    			if (mb->magic == MAGIC2)
    			{
    				printf("Attempt to free already freed memory:\n");
    				trackMBDetails(mb);
    			}
    			else
    			{
    				printf("Invalid free of ptr %p (expr=\"%s\" from %s:%d\n", (void *)ptr, expr, file, line);
    			}
    			return;
            }
            mb->magic = MAGIC2;
            if (mb ==  memblockList)
            {
                memblockList = mb->next;
            }
            // Unlink it. 
            if (mb->next)
               mb->next->prev = mb->prev;
            if (mb->prev)
               mb->prev->next = mb->next;      
            free(mb);
        }
    }
    
    
    void trackListAllocations(void)
    {
    	printf("*** Allocation list start ***\n");
    	if (!memblockList)
    	{
    		printf(">>> EMPTY <<<\n");
    	}
    	else
    	{
    		struct memblk *mb;
    		for(mb = memblockList; mb; mb = mb->next)
    		{
    			trackMBDetails(mb);
    		}
    	}
    	printf("*** Allocation list end ***\n");
    }
    Sample of usage:
    main.c:
    Code:
    #include "trackmalloc.h"
    #include <stdio.h>
    
    int main()
    {
    	int *ptr = malloc(sizeof(int) * 4);
    	int *arrPtr[100];
    	int i;
    	ptr[0] = '0';
    	ptr[1] = '1';
    	ptr[2] = '2';
    	ptr[3] = '3';
    
    	printf("%d %d %d %d\n", ptr[0], ptr[1], ptr[2], ptr[3]);
    
    	for(i = 0; i < 100; i++)
    	{
    		arrPtr[i] = malloc(10 * sizeof(int));
    	}
    
    	free(ptr);
    	
    	for(i = 0; i < 50; i++)
    	{
    		free(arrPtr[i]);
    	}
    
    	trackListAllocations();
    
    	for(; i < 100; i++)
    	{
    		free(arrPtr[i]);
    	}
    
    	return 0;
    }
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  2. #2
    Registered User
    Join Date
    Dec 2008
    Posts
    183
    thats awesome i think this should be sticked.

  3. #3
    Registered User
    Join Date
    Nov 2008
    Location
    Santa Catarina - Brasil
    Posts
    184
    ........ing good!

    speacially for me ?
    eheuheueuhehhe

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by sergioms View Post
    ........ing good!

    speacially for me ?
    eheuheueuhehhe
    No, I just tidied up and fixed the typos/thinkos from the code that I did type in for you - anyone else who finds it handy is welcome to use it.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    396
    malloc() implementations may also propose checking and debugging services, the glibc malloc() and free() calls can be traced by calling first mtrace() and setting the env. var. MALLOC_TRACE to a writeable filename. Reports are less detailed than the memblk structure detailed above, but that may be useful.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by root4 View Post
    malloc() implementations may also propose checking and debugging services, the glibc malloc() and free() calls can be traced by calling first mtrace() and setting the env. var. MALLOC_TRACE to a writeable filename. Reports are less detailed than the memblk structure detailed above, but that may be useful.
    Sure, and MS's library also have similar features.

    The above is more intended to show how you can make your own tracing for the purposes of leak detection. Of course, we could also add more spacing to the front and back of the memory and detect overwrites. In the past (a few years back at work) I implemented a mechanism that holds on to freed memory, and every now and again checks that the freed memory hasn't been written to (by filling it when it is freed with a recognizable pattern so that we can detect the fact that it has been written to).

    But by all means, if the C library supports what you want to do, then use it.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Your code suffers from a mix of spaces and tabs, mats. I assume this is due to your editor (they can be tricky sometimes, I know!).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    Your code suffers from a mix of spaces and tabs, mats. I assume this is due to your editor (they can be tricky sometimes, I know!).
    Visual studio, so yes, I'll blame the editor. [I just pointed the same out to someone else!]

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by matsp
    Visual studio, so yes, I'll blame the editor.
    Just get it to insert spaces only then.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I noticed that it does that sometimes. Why, oh why, MICROSOOOOOOOFT!?!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by laserlight View Post
    Just get it to insert spaces only then.
    Yes, I'm sure there is a setting for that... Just a question of finding it and setting it correctly. Since I mostly use other tools for work, I haven't actually looked into it [and I was under the impression that it would naturally "do the right thing" - but of course proven wrong].

    Now we have more comments on the whitespaces in the code than the actual code...

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problems with shared memory shmdt() shmctl()
    By Jcarroll in forum C Programming
    Replies: 1
    Last Post: 03-17-2009, 10:48 PM
  2. Replies: 4
    Last Post: 01-13-2008, 02:14 AM
  3. Question regarding Memory Leak
    By clegs in forum C++ Programming
    Replies: 29
    Last Post: 12-07-2007, 01:57 AM
  4. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  5. Shared Memory - shmget questions
    By hendler in forum C Programming
    Replies: 1
    Last Post: 11-29-2005, 02:15 AM