How to Know If a Pointer Points to the Heap or the Stack

How to know if a pointer points to the heap or the stack?

There is no way of doing this - and if you need to do it, there is something wrong with your design. There is a discussion of why you can't do this in More Effective C++.

How to determine if returned pointer is on the stack or heap

Distinguishing between malloc/free and new/delete is generally not possible, at least not in a reliable and/or portable way. Even more so as new simply wrapps malloc anyway in many implementations.

None of the following alternatives to distinguish heap/stack have been tested, but they should all work.

Linux:

  1. Solution proposed by Luca Tettananti, parse /proc/self/maps to get the address range of the stack.
  2. As the first thing at startup, clone your process, this implies supplying a stack. Since you supply it, you automatically know where it is.
  3. Call GCC's __builtin_frame_address function with increasing level parameter until it returns 0. You then know the depth. Now call __builtin_frame_address again with the maximum level, and once with a level of 0. Anything that lives on the stack must necessarily be between these two addresses.
  4. sbrk(0) as the first thing at startup, and remember the value. Whenever you want to know if something is on the heap, sbrk(0) again -- something that's on the heap must be between the two values. Note that this will not work reliably with allocators that use memory mapping for large allocations.

Knowing the location and size of the stack (alternatives 1 and 2), it's trivial to find out if an address is within that range. If it's not, is necessarily "heap" (unless someone tries to be super smart-ass and gives you a pointer to a static global, or a function pointer, or such...).

Windows:

  1. Use CaptureStackBackTrace, anything living on the stack must be between the returned pointer array's first and last element.
  2. Use GCC-MinGW (and __builtin_frame_address, which should just work) as above.
  3. Use GetProcessHeaps and HeapWalk to check every allocated block for a match. If none match for none of the heaps, it's consequently allocated on the stack (... or a memory mapping, if someone tries to be super-smart with you).
  4. Use HeapReAlloc with HEAP_REALLOC_IN_PLACE_ONLY and with exactly the same size. If this fails, the memory block starting at the given address is not allocated on the heap. If it "succeeds", it is a no-op.
  5. Use GetCurrentThreadStackLimits (Windows 8 / 2012 only)
  6. Call NtCurrentTeb() (or read fs:[18h]) and use the fields StackBase and StackLimit of the returned TEB.

How can I tell whether a pointer points to the stack or to the heap?

You can't realistically hope to distinguish between stack and heap memory in this way. You say "the stack", but there are many. One per thread. You'd need to check the reserved addresses of all the stacks. And how will you find a list of all the stacks to do that checking without encountering a terrible race condition?

It is folly to try to get a record to behave differently depending on whether it is allocated automatically on the stack, or dynamically on the heap. Those behaviour variations need to be handled by the consumer of the record.

A scenario to make you re-consider is that where your record is contained inside another type (record or class). The instance of the containing type may be heap allocated but you must not free the contained record, even though it resides on the heap.

The bottom line of heap allocation is that you need to remember when you allocated off the heap and ensure that you free anything allocated on the heap. If you forget who owns the memory by a pointer you are doing it wrong.

Don't continue down the dead end trail that you have started along.

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

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.

Where are pointers in C++ stored, on the stack or in the heap?

Your understanding may be correct, but the statements are wrong:

A pointer to object m has been allocated on the stack.

m is the pointer. It is on the stack. Perhaps you meant pointer to a Member object.

The object m itself (the data that it carries, as well as access to its methods) has been allocated on the heap.

Correct would be to say the object pointed by m is created on the heap

In general, any function/method local object and function parameters are created on the stack. Since m is a function local object, it is on the stack, but the object pointed to by m is on the heap.

Check if a pointer points to allocated memory on the heap

There's no standard way to do this, but various malloc debugging tools may have a way of doing it. For example, if you use valgrind, you can use VALGRIND_CHECK_MEM_IS_ADDRESSABLE to check this and related things

Checking if a pointer is allocated memory or not

You cannot check, except some implementation specific hacks.

Pointers have no information with them other than where they point. The best you can do is say "I know how this particular compiler version allocates memory, so I'll dereference memory, move the pointer back 4 bytes, check the size, makes sure it matches..." and so on. You cannot do it in a standard fashion, since memory allocation is implementation defined. Not to mention they might have not dynamically allocated it at all.

You just have to assume your client knows how to program in C. The only un-solution I can think of would be to allocate the memory yourself and return it, but that's hardly a small change. (It's a larger design change.)

Check if memory is on the Heap?

While there are system specific approaches which will probably be able to tell whether memory is from heap or from a stack, that actually doesn't really help: you may have got a pointer to a member of another object on the heap. The memory would be on the heap but you are still not responsible for deleting the object. Put differently: do not go down the path you are on!

The proper way to deal with the problem is to make the ownership semantics blatantly clear in the interface and go with that. There are essentially two directions you can take:

  1. Your class can deliberately not take over responsibility for the pointer passed in the constructor! Instead, it is the responsibility of the user of your class to deal with these objects and to guarantee that they are valid while your objects exists. If you can get pointers to stack (or member) objects the user already has to guarantee the validity of these objects anyway and for other ways it may be entirely trivial for the user to deal with them, e.g., by managing them via a std::unique_ptr<OtherClass>.
  2. Your class takes responsibility of all objects passed and it will delete all of them. It becomes the responsibility of the caller to not pass pointers to objects managed elsewhere, e.g., to objects on the stack or member objects.

There is sort of a hybrid approach where your class takes responsibility of objects some times but not always. However, the implementations of such an approach is really a combination of the two approaches above: you'd take a suitable smart pointer as constructor argument and it is the user's responsibility to make sure that the smart pointer is constructed appropriately by the user of your class. For example, your class could take a std::shared_ptr<OtherClass> for which the normal construction will delete the object. When the user wants to pass in a pointer to an otherwise owned object the std::shared_ptr<OtherClass> would be constructed with a deleter which does not delete the pointer. Here is a simple program demonstrating the two different management strategies for std::shared_ptr:

#include <iostream>
#include <memory>

struct foo {
char const* name;
foo(char const* name)
: name(name) {
std::cout << "foo::foo(" << name << "): " << this << "\n";
}
~foo() {
std::cout << "foo::~foo(" << name << "): " << this << "\n";
}
};

int main() {
std::shared_ptr<foo>(new foo("heap"));
foo f("stack");
std::shared_ptr<foo>(&f, [](auto){});
}

Does a pointer point to the stack or heap after using delete?

Deleting p signals to whoever manages the memory (the OS) that the underlying space is now free to be re-allocated by someone else for their own use. p, however, still points to the same memory location and can be dereferenced to obtain the value of what's in that memory -- note that since that memory may now be used by someone else, the underlying bits might be different from what they were before.

C++ Is it possible to determine whether a pointer points to a valid object?

No, you can't. Why? Because it would be expensive to maintain meta data about what constitutes a valid pointer and what doesn't, and in C++ you don't pay for what you don't want.

And you don't want to check whether a pointer is valid, because you know where a pointer comes from, either because it's a private part of your code that you control, or because you specified it in your external-facing contracts.



Related Topics



Leave a reply



Submit