Thread: Figuring out if address is in heap or stack

  1. #1
    Registered User
    Join Date
    Feb 2013
    Posts
    23

    Figuring out if address is in heap or stack

    I'm trying to code something that will print an error statement if the user tries to free something never malloc-ed (like if they try to free the address of a local variable declared on the stack).

    I'm not quite sure how to approach this other than to try to check if the address of the variable attempted to be freed is in the stack (or check if the address of the variable attempted to be freed is NOT in the heap) -- however, this is difficult because I don't know what memory addresses would separate teh stack from the heap and how to go about finding that out. Any advice?

    Thank you!

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Not all implementations make a distinction between heap, stack, and other areas of memory, so you can't just rely on checking the value of a pointer is in some range.

    Generally speaking, you would need to find some way to track all pointers that are returned by malloc()/calloc()/realloc(). Then all you need to do is check if a supplied pointer is one of the tracked values, and issue an error message.

    To do that, there are two possible approaches.

    1) Dig into compiler/library specific data structures maintained internally by malloc()/calloc()/realloc()/free() - or the system calls that they use. One problem with this approach is that it is highly specific to the implementation (compiler and standard library). The main problem is that the implementation of malloc()/calloc()/realloc()/free() is often not documented, so you would be relying on reverse engineering or guesswork.

    2) Write your own wrappers for malloc()/calloc()/realloc()/free() that call the originals, but that keep track of all allocations and deallocations. The problem with this is that it requires your programs to use your wrappers, rather than calling malloc()/calloc()/realloc()/free() directly, otherwise the tracking will be incorrect (false negatives and false positives).

    Bear in mind that the NULL pointer is special to free() and realloc().


    Personally, I consider it is better to be disciplined enough in your usage of malloc()/calloc()/realloc()/free() so you avoid such problems. It's easier to avoid a problem than try to detect its symptoms. Sadly, people often prefer to hack or grow their programs organically and don't think about avoiding problems until they encounter effects of a hard-to-find flaw in the their program.

    There are tools like valgrind - a suite of tools for debugging and profiling, which can detect/report memory management problems.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Overall your idea is quite pointless since this is not a common error. It's essentially a logic error and you simply cannot protect against logic errors in general.

    However:

    In Linux, for example, the ultimate heap allocator is sbrk(). All it does is extend the data segment, which begins at a some address and grows upwards. All allocations will be greater than or equal to this starting address. On the other hand, the stack starts at the "top" of memory and grows downwards towards the current end of the heap.

    So it would be very easy to tell if something is on the stack or not. You'd simply test whether the address is greater than the address of the last variable added to the stack.

    But that's not enough since statically allocated variables (such as globals) are not on the stack but are instead below the bottom of the heap. To detect them you could do an initial malloc and store that address as the bottom of the heap.

    Code:
    void *bottom_of_heap;
    
    void mymalloc_init(void)
    {
        bottom_of_heap = malloc(sizeof(int));
    }
    
    void myfree(void *ptr)
    {
        int bottom_of_stack;
        if (ptr > &bottom_of_stack || ptr < bottom_of_heap) {
            fprintf(stderr, "Attempt to free non-heap memory.\n");
            exit(THIS_GUYS_NUTS);
        }
        free(ptr);
    }
    I haven't tested it or even thought about it that much but I believe that something like that would work on Linux. It may even work on Windows. Any solution would be implementation specific, though.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  4. #4
    Registered User
    Join Date
    Apr 2013
    Posts
    1,646
    For windows 32 bit console programs created by microsoft compilers the order is: stack, heap, statics (program image), heap, where some of the heap is before statics and some is after. Note that these are virtual addresses that make a virtual continuous address space out of scattered physical memory pages. Small allocations are usually in the heap before the statics, large allocations (2 MB or more) after the statics.

  5. #5
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by rcgldr View Post
    For windows 32 bit console programs created by microsoft compilers the order is: stack, heap, statics (program image), heap, where some of the heap is before statics and some is after. Note that these are virtual addresses that make a virtual continuous address space out of scattered physical memory pages. Small allocations are usually in the heap before the statics, large allocations (2 MB or more) after the statics.
    What's you souce on that?
    Here's a diagram that doesn't fit that model:
    http://www.cs.uleth.ca/~holzmann/C/s...morylayout.gif
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  6. #6
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    @rcgldr, Still waiting for that source.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  7. #7
    Registered User
    Join Date
    Apr 2013
    Posts
    1,646
    Quote Originally Posted by rcgldr View Post
    For windows 32 bit console programs created by microsoft compilers the order is: stack, heap, statics (program image), heap, where some of the heap is before statics and some is after. Note that these are virtual addresses that make a virtual continuous address space out of scattered physical memory pages. Small allocations are usually in the heap before the statics, large allocations (2 MB or more) after the statics.
    Quote Originally Posted by oogabooga View Post
    What's you source on that?
    I wrote a program that displays the addresses of static, stack based, and heap based variables, compiled with Visual C / C++ 4.0, and with Visual Studio 2005, running on Windows XP 32 bit. The results were similar. For a small program, the stack goes from 30000 hex to 12FFFF hex (1MB), first heap segment between stack and program image, usually around 330000 hex, statics between 400000 hex and 401000 hex, program code base at 401000 hex, and second heap segment after program image, from 40A000 hex to 7C800000 hex (where kernel.dll and other os stuff is mapped). The virtual address ranges for the heap segments are just "reserved", and not valid until malloc or new are used. These addresses would change for a large program or one compiled to have a large stack. There are debuggers and/or trainers for windows that can display the memory map for a process.
    Last edited by rcgldr; 09-18-2013 at 03:26 PM.

  8. #8
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Very interesting! Thanks for the info.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  9. #9
    Registered User
    Join Date
    Apr 2013
    Posts
    1,646
    Note that Windows Vista and later version randomize the memory map addresses somewhat to reduce the chance of buffer overflow viruses from working.

  10. #10
    young grasshopper jwroblewski44's Avatar
    Join Date
    May 2012
    Location
    Where the sidewalk ends
    Posts
    294
    Address space layout randomization - Wikipedia, the free encyclopedia

    I would say that grumpy's original idea would be best.
    "Simplicity is the ultimate sophistication." - Leonardo da Vinci

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,398
    C doesn't specify that a stack must exist -- there could be no stack at all.

    However, if there is a stack, then it must exist somewhere between &argc (the first parameter to main()) and wherever the top of the stack happens to be -- assuming standard calling conventions, you could do something like this:

    Code:
    void* TopOfStack;
    
    int main(int argc, char **argv)
    {
        TopOfStack = &argc;
    }
    
    int IsAddressOnTheStack(void* addr)
    {
        return addr >= &addr && addr <= TopOfStack;
    }
    EDIT: I still think it's a bad idea. There are situations where this won't work, such as in a thread (each thread has a different stack).
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Stack or Heap ?
    By Stuart Dickson in forum C Programming
    Replies: 4
    Last Post: 05-06-2010, 12:40 PM
  2. Should I use the Heap or the Stack?
    By Swerve in forum C++ Programming
    Replies: 2
    Last Post: 10-08-2009, 12:38 PM
  3. heap or stack?
    By sawer in forum C++ Programming
    Replies: 4
    Last Post: 01-24-2006, 02:36 AM
  4. iterators heap or stack
    By curlious in forum C++ Programming
    Replies: 2
    Last Post: 12-22-2004, 03:40 PM
  5. Stack and Heap
    By Barjor in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 01-29-2002, 09:11 AM