From: pfultz2 on
I want detect if a pointer is pointing to memory on the heap or the
stack, so I came up with this approach:

bool isOnHeap(void * p)
{
int i = 0;
int * s = &i;
return (p > s);
}

I dont if this is the best or most portable way to do it. And im not
sure how well it works for static and global variables, do they start
on the end of memory? or at the begining? The reason why i want to do
this is need to delete pointers sometimes, and some of them point to
memory on the stack, so therefore i dont want to delete them, I could
use type erasure and create a seperate class to handle the memory and
use some form of custom deallocators, but then it would either cost me
an extra pointer or double dereferencing, and i was trying to think of
a neater way to do it. thanks.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Sujal on
On Apr 1, 12:39 am, pfultz2 <pful...(a)yahoo.com> wrote:
> I want detect if a pointer is pointing to memory on the heap or the
> stack, so I came up with this approach:
>
> bool isOnHeap(void * p)
> {
> int i = 0;
> int * s = &i;
> return (p > s);
>
> }
>
> I dont if this is the best or most portable way to do it. And im not
> sure how well it works for static and global variables, do they start
> on the end of memory? or at the begining? The reason why i want to do
> this is need to delete pointers sometimes, and some of them point to
> memory on the stack, so therefore i dont want to delete them, I could
> use type erasure and create a seperate class to handle the memory and
> use some form of custom deallocators, but then it would either cost me
> an extra pointer or double dereferencing, and i was trying to think of
> a neater way to do it. thanks.

{ edits: quoted banner removed. please keep readers in mind when quoting. -mod }

Hi,
I don't think, the approach you are using is correct. It is not
portable code. Different architecture using different type to handle
stack and Heap area. That is totally OS architecture dependent.
BTW, As you also asked about where static/global variables are
stored then answer is they are stored in BSS area which is part of
Data segment. Constants are generally stored in TEXT area or Code
segment (Depends upon compiler). C/C++ standard does not talk that any
of these types of variable to be stored anywhere specifically.

thanks,
Sujal Sheth


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Martin B. on
pfultz2 wrote:
> I want detect if a pointer is pointing to memory on the heap or the
> stack, so I came up with this approach:
>
> bool isOnHeap(void * p)
> {
> int i = 0;
> int * s = &i;
> return (p > s);
> }
>
> I dont if this is the best or most portable way to do it. And im not
> sure how well it works for static and global variables, do they start
> on the end of memory? or at the begining? The reason why i want to do
> this is need to delete pointers sometimes, and some of them point to
> memory on the stack, so therefore i dont want to delete them ...

This does not work!

I'm not even aware of any non-portable (say Windows specific) way to
determine where an arbitrary pointer value belongs. (There is the
HeapValidate function but I'm not convinced that it would work.)

cheers,
Martin

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nick Hounsome on
On 31 Mar, 20:39, pfultz2 <pful...(a)yahoo.com> wrote:
> I want detect if a pointer is pointing to memory on the heap or the
> stack, so I came up with this approach:
>
> bool isOnHeap(void * p)
> {
> int i = 0;
> int * s = &i;
> return (p > s);
>
> }
>
> I dont if this is the best or most portable way to do it. And im not
> sure how well it works for static and global variables, do they start
> on the end of memory? or at the begining? The reason why i want to do
> this is need to delete pointers sometimes, and some of them point to
> memory on the stack, so therefore i dont want to delete them, I could
> use type erasure and create a seperate class to handle the memory and
> use some form of custom deallocators, but then it would either cost me
> an extra pointer or double dereferencing, and i was trying to think of
> a neater way to do it. thanks.

This is such a bad idea I checked the date to make sure it wasn't
posted today - April first.

Not only is it not portable it is fundamentally a bad design.
Memory problems are best avoided by only deleting objects in the class
that allocates them.

If you realy want to go down this route then I would suggest a smart
pointer that explicitly knows whether or not the
object should be deleted or not (via a ctor parameter) - the only
overhead is an extra bool.



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: George Neuner on
On Wed, 31 Mar 2010 13:39:59 CST, pfultz2 <pfultz2(a)yahoo.com> wrote:

>I want detect if a pointer is pointing to memory on the heap or the
>stack, so I came up with this approach:
>
>bool isOnHeap(void * p)
>{
> int i = 0;
> int * s = &i;
> return (p > s);
>}
>
>I dont if this is the best or most portable way to do it. And im not
>sure how well it works for static and global variables, do they start
>on the end of memory? or at the begining? The reason why i want to do
>this is need to delete pointers sometimes, and some of them point to
>memory on the stack, so therefore i dont want to delete them, I could
>use type erasure and create a seperate class to handle the memory and
>use some form of custom deallocators, but then it would either cost me
>an extra pointer or double dereferencing, and i was trying to think of
>a neater way to do it. thanks.

In general there's no portable way to do it because there is no
standard program memory layout. What you can do, though, is assume
that the stack is contiguous, determine its address range and then see
whether the target address is within the range.

Something like:

*******************

void* stack_base;


bool ptr_in_stack( const void* target )
{
bool retval;
int here;

void *stack_top = &here;
if ( stack_base > stack_top )
// stack grows down
retval = (stack_base > target) && (target >= stack_top);
else
// stack grows up
retval = (stack_base <= target) && (target < stack_top);

return retval;
}


int main( void )
{
int here;

stack_base = &here;

:

return 0;
}

*******************

The stack check works on Unix/Linux and Windows because their stacks
are contiguous - but there may be other platforms for which it won't
work (although I've yet to meet such a platform).

Note that a false result (not in stack) doesn't actually mean the
target address is within the heap ... it could be a code address or
outside the process's address space entirely.



To check that a pointer is within the heap on Unix/Linux you can do
something similar to the stack check. sbrk(0) will give you the high
end of the heap, but there isn't any good way to get the low end. An
approximation can be found by taking the highest address from among
your global variables (the dynamic heap starts somewhere above the
globals), but to be more accurate you'd need to look into the workings
of your C++ runtime allocator. You *cannot* simply malloc()/new
something at the beginning of the program and assume that it will be
at the low end of the heap.

*******************

void* heap_base;

bool ptr_in_heap( const void* target )
{
void *heap_top = sbrk(0);
return (heap_base <= target) && (target < heap_top);
}

*******************



Windows is more difficult because processes may have multiple heaps -
each attached DLL may have its own heap and the program itself may
have created additional ones beyond the default heap. However,
Windows is also more helpful because it provides standard functions
for examining the heaps.

The following code works for Win32, for Win64 you need to change it to
use the appropriate structures for 64-bit:

*******************

#include <windows.h>
#include <Tlhelp32.h>

bool ptr_in_heap( const void* target, const int objectSize = 1 )
{
HANDLE snapshot;
HEAPLIST32 theHeap;
HEAPENTRY32 theBlock;
DWORD pid;
BOOL moreHeaps, moreBlocks;

if ( IsBadReadPtr( target, objectSize ) )
{
return false;
}

pid = GetProcessId( GetCurrentProcess() );
snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPHEAPLIST, pid );

theHeap.dwSize = sizeof(theHeap);
moreHeaps = Heap32ListFirst( snapshot, &theHeap );
while ( moreHeaps )
{
theBlock.dwSize = sizeof(theBlock);
moreBlocks = Heap32First( &theBlock, theHeap.th32ProcessID,
theHeap.th32HeapID );
while ( moreBlocks )
{
char* lo = (char*) theBlock.dwAddress;
char* hi = lo + theBlock.dwBlockSize;
if ((lo <= target) && (target <= hi))
{
return true;
}
moreBlocks = Heap32Next( &theBlock );
}

moreHeaps = Heap32ListNext( snapshot, &theHeap );
}

return false;
}

*******************


Finally, note that none of this tells you whether the target address
is a valid program object ... all you can safely determine is whether
the address is legal.

George

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]