|
-
October 19th, 2002, 03:51 AM
#1
pointer
How could I know if a pointer is on the stack or on heap?!
(How could I know if a pointer was allocated with new or with a reference?)
-
October 19th, 2002, 11:22 AM
#2
I don't think there is a way....
Although I don't understand why you would need to know this, as unless you are receiving a pointer from a function that you did not write, you should know if the data pointed at by the pointer is on the stack or the heap.
Why would you need to know?
-
October 20th, 2002, 07:30 AM
#3
it's simple!
call _msize. if it return 0 or something like that - object in stack!
Note. It's a Microsoft specific.
-
October 20th, 2002, 09:14 AM
#4
When compiled for debug, _msize() produces an ASSERT if the object was not allocated with malloc() family of functions.
-
October 20th, 2002, 10:24 AM
#5
James,
(How could I know if a pointer was allocated with new or with a reference?)
I believe you mean an address operator - not a reference.
That being said, I don't know any generic way you can tell whether a
pointer contains an address to stack or heap memory.
regards, willchop
-
October 20th, 2002, 11:55 AM
#6
There is no generic C++ way to do this. This is covered in one of Scott Meyer's Effective C++ books (Effective C++ or More Effective C++, I don't remember which one).
Since C++ doesn't assume that there is even a "stack", the answer to your question is highly system, compiler, and OS dependent.
Regards,
Paul McKenzie
-
October 20th, 2002, 11:56 AM
#7
Small mistake....
I didn't post this question.
Not a big deal - but you typed James, and then quoted the poster of the question.
-
October 20th, 2002, 04:03 PM
#8
-
October 21st, 2002, 02:45 PM
#9
it's simple!
call _msize. if it return 0 or something like that
This function appears to only keep track of the actual
pointer to the memory allocated by malloc - not valid addresses
within that block. For this reason the function may not provide
accurate results.
For example:
Code:
char* buffer = static_cast<char*>(malloc(1000 * sizeof(char)));
if (!buffer) return;
char* mid_buffer = buffer + 499;
printf("sizeof buffer: %d\n", _msize(buffer));
printf("sizeof mid_buffer: %d\n", _msize(mid_buffer));
free(buffer);
The mid_buffer is pointing to memory that was dynamically
allocated, but _msize() fails to report so.
regards, willchop
-
October 21st, 2002, 04:29 PM
#10
(How could I know if a pointer was allocated with new or with a reference?)
You could either create a new operator for the specific object you want to check, or if it's for multiple objects, you could over write the global new operator.
Within your new operator, you can update a global vector of pointers, and then LATER, check the vector to see if your pointer is listed in the vector.
-
October 21st, 2002, 04:56 PM
#11
Here's an example:
#include <iterator>
#include <new>
#include <map>
class foo {
public:
int x;
void* operator new(size_t)
{
foo* ptr = ::new foo;
FooPtrs[ptr] = 0;
return ptr;
}
void operator delete(void* ptr)
{
FooPtrs.erase((foo*)ptr);
: elete ptr;
}
void* operator new[] (size_t s)
{
foo* ptr = ::new foo[s];
for(foo* p = ptr;p < ptr+s;++p)
FooPtrs[p]=s;
return ptr;
}
void operator delete[] (void* ptr)
{
size_t s = FooPtrs[(foo*)ptr];
for(foo* p = (foo*)ptr;p < (foo*)ptr+s;++p)
FooPtrs.erase(p);
}
static std::map<const foo*, size_t> FooPtrs;
static bool IsCreatedByNew(const foo* ptr)
{
return (FooPtrs.find(ptr) != FooPtrs.end());
}
};
std::map<const foo*, size_t> foo::FooPtrs;
int main(int argc, char* argv[])
{
foo *pXa = new foo[5];
foo *pX = new foo;
foo NotPtr;
foo NotPtrA[5];
bool t1 = foo::IsCreatedByNew(pXa);
pXa++;
bool t2 = foo::IsCreatedByNew(pXa++);
bool t3 = foo::IsCreatedByNew(pX);
bool t4 = foo::IsCreatedByNew(&NotPtr);
bool t5 = foo::IsCreatedByNew(&NotPtrA[0]);
bool t6 = foo::IsCreatedByNew(&NotPtrA[2]);
delete [] pXa;
delete pX;
bool t7 = foo::IsCreatedByNew(pX);
bool t8 = foo::IsCreatedByNew(pXa++);
return 0;
}
-
October 21st, 2002, 04:58 PM
#12
Correction:
Code:
#include <iterator>
#include <new>
#include <map>
class foo {
public:
void* operator new(size_t)
{
foo* ptr = ::new foo;
FooPtrs[ptr] = 0;
return ptr;
}
void operator delete(void* ptr)
{
FooPtrs.erase((foo*)ptr);
::delete ptr;
}
void* operator new[] (size_t s)
{
foo* ptr = ::new foo[s];
for(foo* p = ptr;p < ptr+s;++p)
FooPtrs[p]=s;
return ptr;
}
void operator delete[] (void* ptr)
{
size_t s = FooPtrs[(foo*)ptr];
for(foo* p = (foo*)ptr;p < (foo*)ptr+s;++p)
FooPtrs.erase(p);
}
static std::map<const foo*, size_t> FooPtrs;
static bool IsCreatedByNew(const foo* ptr)
{
return (FooPtrs.find(ptr) != FooPtrs.end());
}
};
std::map<const foo*, size_t> foo::FooPtrs;
int main(int, char**)
{
foo *pXa = new foo[5];
foo *pX = new foo;
foo NotPtr;
foo NotPtrA[5];
bool t1 = foo::IsCreatedByNew(pXa);
pXa++;
bool t2 = foo::IsCreatedByNew(pXa++);
bool t3 = foo::IsCreatedByNew(pX);
bool t4 = foo::IsCreatedByNew(&NotPtr);
bool t5 = foo::IsCreatedByNew(&NotPtrA[0]);
bool t6 = foo::IsCreatedByNew(&NotPtrA[2]);
delete [] pXa;
delete pX;
bool t7 = foo::IsCreatedByNew(pX);
bool t8 = foo::IsCreatedByNew(pXa++);
return 0;
}
-
October 21st, 2002, 07:06 PM
#13
thank you all
Thanx...It works!
How about a generic method? a template seems to be more accurate here...
-
October 21st, 2002, 07:06 PM
#14
Originally posted by Axter
Correction:
Code:
void* operator new(size_t)
{
foo* ptr = ::new foo;
FooPtrs[ptr] = 0;
return ptr;
}
I hope the compiler is smart enough not to call the constructor twice.
First of all, you don't check if calling global new fails or not. But in this case, it's not safe to do what this overload of new does. If global new succeeds - the constructor is called for the object. This could be disastrous if the class allocates memory in it's default constructor. Because when the overloaded new returns and succeeded - it's calls the constructor again. As you know, the constructor is the first function called in an object's life - therefore the member variable (the pointer) that points at memory is thought of as 'garbage' by the 2nd call to the constructor. Therefore you have a memory leak.
Last edited by JamesSchumacher; October 21st, 2002 at 07:19 PM.
-
October 21st, 2002, 11:31 PM
#15
If global new succeeds - the constructor is called for the object. This could be disastrous if the class allocates memory in it's default constructor. Because when the overloaded new returns and succeeded - it's calls the constructor again. As you know, the constructor is the first function called in an object's life - therefore the member variable (the pointer) that points at memory is thought of as 'garbage' by the 2nd call to the constructor. Therefore you have a memory leak.
You're absolutely right. I assume the constructor would be called only when the global operator is called.
I modified the code to use malloc and free instead. That will prevent the double constructor and double destructor calls.
As this is just an example, I leave it up to the questioner to add extra required validation.
Code:
#include <iostream>
#include <iterator>
#include <new>
#include <map>
#include <stdlib.h>
class foo {
public:
foo()
{
++Qty;
std::cout << "Passing through constructor " << Qty << std::endl;
}
~foo()
{
--Qty;
std::cout << "Passing through destructor " << Qty << std::endl;
}
void* operator new(size_t)
{
foo* ptr = (foo*)malloc(sizeof(foo));
FooPtrs[ptr] = 0;
return ptr;
}
void operator delete(void* ptr)
{
FooPtrs.erase((foo*)ptr);
free(ptr);
}
void* operator new[] (size_t s)
{
foo* ptr = (foo*)malloc(sizeof(foo)*s);
for(foo* p = ptr;p < ptr+s;++p)
FooPtrs[p]=s;
return ptr;
}
void operator delete[] (void* ptr)
{
free(ptr);
size_t s = FooPtrs[(foo*)ptr];
for(foo* p = (foo*)ptr;p < (foo*)ptr+s;++p)
FooPtrs.erase(p);
}
static std::map<const foo*, size_t> FooPtrs;
static bool IsCreatedByNew(const foo* ptr)
{
return (FooPtrs.find(ptr) != FooPtrs.end());
}
static int Qty;
};
int foo::Qty = 0;
std::map<const foo*, size_t> foo::FooPtrs;
void SomeFunction()
{
foo *pX = new foo;
foo *pXa = new foo[5];
foo NotPtr;
foo NotPtrA[5];
bool t1 = foo::IsCreatedByNew(pXa);
pXa++;
bool t2 = foo::IsCreatedByNew(pXa++);
bool t3 = foo::IsCreatedByNew(pX);
bool t4 = foo::IsCreatedByNew(&NotPtr);
bool t5 = foo::IsCreatedByNew(&NotPtrA[0]);
bool t6 = foo::IsCreatedByNew(&NotPtrA[2]);
delete pX;
pXa--;
pXa--;
delete [] pXa;
bool t7 = foo::IsCreatedByNew(pX);
bool t8 = foo::IsCreatedByNew(pXa++);
}
int main(int, char**)
{
SomeFunction();
return 0;
}
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|