Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find out whether a pointer is pointing at the stack, heap or program text?

Tags:

c

pointers

Is there a way to find out whether a pointer is pointing at a location in:

  • the stack
  • the heap
  • or the program (and if so, which section e.g. elf .text)?

Also, can this be done portably (Linux 64/32 bit, OSX and Windows 7+)?

follow up:

I'm not trying to find out if something has been malloc'd.

I want to efficiently distinguish void* pointers to functions in the program from void* pointers to data on the stack or heap.

This is for a language runtime written in C, not a "normal" C program.

This answer has been the most useful so far: Checking if something was malloced

like image 274
fadedbee Avatar asked May 03 '13 13:05

fadedbee


People also ask

Do pointers point to stack or heap?

Pointer is allocated on the stack and the object it is pointing to is allocated on the heap. A pointer is an object.

Can a pointer be on the heap?

They can exist on the heap, on the stack, as static variables or anything else you can do with any other type. You can create pointers or references to them.

How do you declare a pointer on the heap?

You can declare a pointer and have it point to (make its value be) that location in memory for the variable called count as follows: int *ptr; ptr = &count; The asterisk (*) in a declaration defines to the system that ptr is to be a pointer and the int is the data type to which it will point.

Is a pointer pointing to a memory location that has been deleted?

Dangling pointers arise when an object is deleted or de-allocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the de-allocated memory. In short pointer pointing to non-existing memory location is called dangling pointer.

How to check if a pointer points to stack or heap?

So if we get a pointer, just check whether the pointer falls between the above two memory locations. If it does, then it can be considered a pointer to some stack object. So here is my API to find whether the pointer points to stack or heap. // This function will return true if the pointer points to stack.

What is the difference between a pointer and a stack?

This example uses a pointer to put an ordinary number on the heap, but you can stuff arrays and big objects there too. If you need more space, the heap grows to fit your needs. It’s slower and less efficient than the stack, but far more flexible. When you need to find your data on the heap, you use the pointer.

How does a function know if a pointer is off the stack?

If the function determines that the pointer is pointing to a memory location that's off the stack limits, then the function only knows that much - it's off the stack limits. It won't know if the pointer is actually pointing to something on the heap, or if it's just plain uninitialized.

What is the difference between heap and stack in C?

If you need more space, the heap grows to fit your needs. It’s slower and less efficient than the stack, but far more flexible. When you need to find your data on the heap, you use the pointer. It’s a bit like following a numeric code at the library to find the shelf that has the book you want.


1 Answers

You cannot do what you want in a portable way, because the C language standard does not specify the stack, program area, and heap as distinct areas. Their location can depend on the processor architecture, the operating system, the loader, the linker, and the compiler. Trying to guess where a pointer is pointing is breaking the abstraction provided by C, so you probably you shouldn't be doing that.

Nevertheless, there are ways to write code that will make a correct guess for a specific environment. You do that by examining the addresses of existing objects, and looking for patterns. Consider the following program.

#include <stdlib.h>
#include <stdio.h>

void
function()
{
    int stack2;

    printf("stack2:  %15p\n", &stack2);
}

int
main(int argc, char *argv[])
{
    int stack;
    void *heap = malloc(1);
    void *heap2 = malloc(1);

    printf("program: %15p\n", main);
    printf("heap:    %15p\n", heap);
    printf("heap2:   %15p\n", heap2);
    printf("stack:   %15p\n", &stack);
    function();
    return 0;
}

By examining its output you can see a pattern, such as the following on x64 Linux.

program:        0x400504
heap:          0x1675010
heap2:         0x1675030
stack:    0x7fff282c783c
stack2:   0x7fff6ae37afc

From the above you can determine that (probably) the heap grows up from 0x1675010, anything below it is program code (or static data, which you didn't mention), and that the stack grows in an unpredictable manner (probably due to stack randomization) around a very large address, like 0x7fff282c783c.

Compare this with the output under 32-bit Intel Linux:

program:       0x804842f
heap:          0x804b008
heap2:         0x804b018
stack:        0xbf84ad38
stack2:       0xbf84ad14

Microsoft Windows and the 32-bit Microsoft C compiler:

program:        01271020
heap:           002E3B00
heap2:          002E3B10
stack:          0024F978
stack2:         0024F964

gcc under Windows Cygwin:

program:        0040130B
heap:           00A41728
heap2:          00A417A8
stack:          0028FF44
stack2:         0028FF14

gcc under Intel 32-bit FreeBSD:

program:       0x8048524
heap:          0x804b030
heap2:         0x804b040
stack:        0xbfbffb3c
stack2:       0xbfbffb1c

gcc under Intel 64-bit FreeBSD:

program:        0x400770
heap:        0x801006058
heap2:       0x801006060
stack:    0x7fffffffdaec
stack2:   0x7fffffffdabc

gcc under SPARC-64 FreeBSD:

program:        0x100860
heap:         0x40c04098
heap2:        0x40c040a0
stack:     0x7fdffffe9ac
stack2:    0x7fdffffe8dc

PowerPC running MacOS X:

program:          0x1ed4
heap:           0x100120
heap2:          0x100130
stack:        0xbffffba0
stack2:       0xbffffb38

PowerPC running Linux:

program:      0x10000514
heap:         0x100c6008
heap2:        0x100c6018
stack:        0xbff45db0
stack2:       0xbff45d88

StrongARM running NetBSD:

program:          0x1c5c
heap:             0x5030
heap2:            0x5040
stack:        0xefbfdcd0
stack2:       0xefbfdcb4

and ARMv6 running Linux:

program:          0x842c
heap:           0xb63008
heap2:          0xb63018
stack:        0xbe83eac4
stack2:       0xbe83eaac

As you can see the possibilities are endless.

like image 181
Diomidis Spinellis Avatar answered Oct 21 '22 12:10

Diomidis Spinellis