C++ allocating dynamic memory in one function and clearing another function - c++

I would like experts review on the following dynamic memory allocation process and suggest whether there are any memory leaks. Following code is not real code in use, but trying understand concept of memory allocations and de-allocation in different ways.
class ObjMapData
{
private:
int* itsMapData;
........
public:
ObjMapData();
~ObjMapData(){if(itsMapData!= NULL) delete[] itsMapData;}
ClearMemory() {if(itsMapData!= NULL) {delete[] itsMapData; itsMapData= NULL}}
.......
void SetMapData(int* ptrData) { itsMapData = ptrData;} // or should I use int*&ptrData??
int* GetMapData() const { return itsMapData;}
}
Now can I do the following without any memory leaks?
bool Function1(ObjMapData& objMyMap)
{
//populate the ptrData with some data values using many different ways
int* ptrData = new int[1000]; // usually a variable from binary file header
......................
objMyMap.SetMapData(ptrData);
//don't want to delete the memory yet
return true;
}
bool Function2(ObjMapData& objMyMap)
{
int* ptrData = objMyMap.GetMapData();
//do some work such as writing updated data into a binary file
}
bool Function3(ObjMapData& objMyMap)
{
//populate the data
bool bStatus = Function1(objMyMap);
int* ptrData = objMyMap.GetMapData();
//update the map data using ptrData variable
..........
bStatus = Function2(objMyMap); // write data to a binary file
objMyMap.ClearMemory(); // not real code in use, but for understanding the concept
bStatus = Function1(objMyMap); // re-allocate memory
ptrData = objMyMap.GetMapData();
//update the map data using ptrData variable
objMyMap.SetMapData(ptrData); // Do I need to set again or member pointer get updated automatically?
return true
}
int main()
{
ObjMapData objMyMap;
bool bStatus = Function3(objMyMap);
//default destructor of objMyMap can take care of the allocated memory cleanup
return 0;
}
Thank you for your time to confirm the dynamic memory allocation..

Although this may seem to be more to do with style than your question about memory leaks, I would handle the data privately within the class:
class ObjMapData
{
private:
int* itsMapData;
// consider adding 'datasize' member variable
........
public:
ObjMapData(){ itsMapData=NULL; }; // initialise member variable(s)!
~ObjMapData(){ delete[] itsMapData;}
ClearMemory() { delete[] itsMapData; itsMapData=NULL; }
.......
void CreateMapData(int size) { ClearMemory(); itsMapData= new int[size]; }
void FillDataFrom( ???? ) { ???? };
int* GetMapData() const { return itsMapData;}
}
You are then in a better position to improve the class by adding copy constructor and assignment methods which will prevent memory leaks when you use the class.
EDIT
You ask:
My concern here is which of the following is right: void
SetMapData(int* ptrData) Vs void SetMapData(int*&ptrData)
Both are 'right' in the sense that both allow the external (to the class) pointer to be copied and used within your class - with respect to 'memory leaks' it depends on which part of your code you want to manage the memory you allocated. You could:
Have a class handle allocation/deallocation internally
Allocate memory, use some class to manipulate it, deallocate memory outside class
Have a class allocate memory and later deallocate it outside the class
Allocate memory and have some class manipulate and deallocate it.
Usually I find 1 and 2 make more sense than 3 or 4. i.e. it is easier to follow what is going on, less likely to hide errors and so on.
However, as far as 'leaking memory' is concerned: it does not matter where the pointer to an allocated memory block is, how it has been copied, assigned or referenced - it is it's value as a memory address which is important. So, as long as you new and delete that memory address correctly you will not leak memory (whether those actions are inside a class or not).
If, in your application, you need to allocate/deallocate the int array external to your class, it does make some sense for the member functions reference the pointer as a hint to the reader that the class is not responsible for its deallocation - but some decent comments should make that clear anyway :)
Over the years I've come across umpteen bugs due to the mishandling of the "passing of ownership" of allocated memory (more so with good ol 'C') where some piece of code has been written assuming either that it has to free a block or someone else will do it.
Does that answer your question or have I missed the point?

Related

What data type to use for the buffer of a custom stack-based allocator?

I want to create my own game engine so I bought a few books one being Game Engine Architecture Second Edition by Jason Gregory and in it he suggests implementing a few custom allocators. One type of allocator the book talked about was a stack-based allocator, but I got confused when reading it. How do you store data in it? What data type do you use? For example, do you use a void*, void**, an array of char[]? The book says you're meant to allocate one big block of memory using malloc in the begining and free it in the end, and "allocate" memory by incrementing a pointer. If you could help explain this more that would be great because I can't seem to find a tutorial that doesn't use std::allocator. I also thought this might help others interested in a custom allocator so I posted the question here.
This is the header file example they give in the book:
class StackAllocator
{
public:
// Represents the current top of the stack.
// You can only roll back to the marker not to arbitrary locations within the stack
typedef U32 Marker;
explicit StackAllocator(U32 stackSize_bytes);
void* alloc(U32 size_bytes); // Allocates a new block of the given size from stack top
Marker getMarker(); // Returns a Marker to the current stack top
void freeToMarker(Marker marker); // Rolls the stack back to a previous marker
void clear(); // Clears the entire stack(rolls the stack back to zero)
private:
// ...
}
EDIT:
After a while I got this working but I don't know if I'm doing it right
Header File
typedef std::uint32_t U32;
struct Marker {
size_t currentSize;
};
class StackAllocator
{
private:
void* m_buffer; // Buffer of memory
size_t m_currSize = 0;
size_t m_maxSize;
public:
void init(size_t stackSize_bytes); // allocates size of memory
void shutDown();
void* allocUnaligned(U32 size_bytes);
Marker getMarker();
void freeToMarker(Marker marker);
void clear();
};
.cpp File
void StackAllocator::init(size_t stackSize_bytes) {
this->m_buffer = malloc(stackSize_bytes);
this->m_maxSize = stackSize_bytes;
}
void StackAllocator::shutDown() {
this->clear();
free(m_buffer);
m_buffer = nullptr;
}
void* StackAllocator::allocUnaligned(U32 size_bytes) {
assert(m_maxSize - m_currSize >= size_bytes);
m_buffer = static_cast<char*>(m_buffer) + size_bytes;
m_currSize += size_bytes;
return m_buffer;
}
Marker StackAllocator::getMarker() {
Marker marker;
marker.currentSize = m_currSize;
return marker;
}
void StackAllocator::freeToMarker(Marker marker) {
U32 difference = m_currSize - marker.currentSize;
m_currSize -= difference;
m_buffer = static_cast<char*>(m_buffer) - difference;
}
void StackAllocator::clear() {
m_buffer = static_cast<char*>(m_buffer) - m_currSize;
}
Okay for simplicity let's say you're tracking a collection of MyFunClass for your engine. It could be anything, and your linear allocator doesn't necessarily have to track objects of a homogenous type, but often that's how it's done. In general, when using custom allocators you're trying to "shape" your memory allocations to separate static data from dynamic, infrequently accessed vs. frequently accessed, with a view towards optimizing your working set and achieving locality of reference.
Given the code you provided, first, you'd allocate your memory pool. For simplicity, assume you want enough space to pool 1000 objects of type MyFunClass.
StackAllocator sa;
sa.Init( 1000 * sizeof(MyFunClass) );
Then each time you need to "allocate" a new block of memory for a FunClass, you might do it like this:
void* mem = sa.allocUnaligned( sizeof(MyFunClass) );
Of course, this doesn't actually allocate anything. All the allocation already happened in Step 1. It just marks some of your already-allocated memory as in-use.
It also doesn't construct a MyFunClass. Your allocator isn't strongly typed, so the memory it returns can be interpreted however you want: as a stream of bytes; as a backing representation of a C++ class object; etc.
Now, how would you use a buffer allocated in this fashion? One common way is with placement new:
auto myObj = new (mem) MyFunClass();
So now you're constructing your C++ object in the memory space you reserved with the call to allocUnaligned.
(Note that the allocUnaligned bit gives you some insight into why we don't usually write our own custom allocators: because they're hard as heck to get right! We haven't even mentioned alignment issues yet.)
For extra credit, take a look at scope stacks which take the linear allocator approach to the next level.

no need to delete struct memory in vector<StructA*>?

i saw some code like below, but i didn't see any delete statement, is there any memory leak problem?
struct RStatus
{
int fid;
int status;
};
void Foo()
{
vector<RStatus*> rsVec;
RStatus* rs = null;
rs = new RStatus(); // memory allocated here!
rs->fid = 0
rs->status = 0;
rsVec.push_back(rs);
}
If you use vector<RStatus*>, then you have to use delete, otherwise you will have a memory leak.
However, if you use vector<RStatus>, then you don't have to use delete — this is recommended1.
1. If you want to use pointers, then the recommendation is that you should be using smart pointers such as std::unique_ptr, or std::shared_ptr.
Yes, you should free your memory allocated :
struct RStatus
{
int fid;
int status;
};
void Foo()
{
vector<RStatus*> rsVec;
RStatus* rs = null;
rs = new RStatus(); // memory allocated here!
rs->fid = 0
rs->status = 0;
rsVec.push_back(rs);
// free :
unsigned int size = rsVec.size();
for (unsigned int i = 0; i < size; i++ )
delete rsVec[i]; // delete because you used new
}
If you don't do that, all the memory will never be released at the vector destruction.
I would suggest you to use std::vector<RStatus> instead of std::vector<RStatus*>.
You may also used smart ptr. You can found some documentation about it here : http://www.cplusplus.com/reference/memory/shared_ptr/
EDIT: As suggested in comments, if an exception is thrown at rsVec.push_back(rs), the memory allocated will be lost, that's why smart pointers would be a better solution. Or again, use std::vector<RStatus> instead.
Yes, there is a memory leak: the pointer to the created structure is lost after the vector is destroyed, and the memory is never released.
Unless someone performs a delete for each element of rsVec before clearing or destroying the vector.
Yes, that code leaks the RStatus.
It also does nothing else: possibly the real code's vector gets passed to some function that takes posession of the vector's contents.
Tracking down memory leaks is generally not a local problem: every use of that pointer has to, in theory, be examine to figure out if it leaks. Techniques like 'if I allocate it, delete it' and RAII (including smart pointers) attempt to make it more local, so you can tell from an incomplete program if there is a leak.
use boost::shared_ptr if you don't want to bother yourself with a deletion of allocated objects.
http://www.boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm
struct RStatus
{
int fid;
int status;
};
void Foo()
{
vector<shared_ptr<RStatus> > rsVec;
shared_ptr<RStatus> rs = shared_ptr<RStatus>(); // empty shared_ptr
rs.reset(new RStatus()); // memory allocated here!
rs->fid = 0
rs->status = 0;
rsVec.push_back(rs); // shared_ptr is copied
}// vector is destroyed and shared_ptrs also
be careful however not to mixed up things using both shared_ptr and ordinary, raw pointers to avoid situation when shared_ptr tries to delete object which is already deleted

Could you give me a real work example of memory leak?

I heard a lot of memory leak vulnerability, but I could not find a real work example of memory leak, could you provide a real work example of memory leak, maybe of some big open source project and explain the solution to me
thx.
It's really simple actually. In your main put:
char* c = new char[4];
Then exit. That's a memory leak. Any new that doesn't get followed by delete is a leak.
This answer has some good examples, but like my comment has said, it will be fairly hard to find a released application with a leak that an outside observer can look at and easily identify.
I am screaming, cursing and yelling everyday about code like this in our (huge) legacy code base:
// returns raw pointer with changing conventions who's the owner...
HelpFoo* Foo::GetFoo(Bar* pBar, OtherFoo* pFoo)
{
// all 'local' variables even those allocated on freestore declared
// and initialized in a large block at the beginning of the function/method
HelpFoo *A = new HelpFoo;
OtherHelpFoo *B, *C;
EvenMore *D = new EvenMore;
// and so on, these blocks can be huge...
// a complicated spaghetti code in here, with dozens of nested 'ifs'
if (/* some expression */) {
} else if (/* some other expression */) {
// and so on... then suddenly:
if (/* some other nested expression */) {
// I forgot that I've allocated other memory at the beginning...
return A;
}
}
// some miserably written logic here and suddenly
if (D) delete D; return A;
// call to some other function with cryptical name without any
// kind of knowledge what happens with the resource:
FooTakesReferenceToPointer(&A);
// suddenly returning something completely different
// what should I free, A, D...?
return C;
}
I tried to write in comments what the problems are. Clearly, forget about exceptions. The spaghetti code is so bad that nobody can tell what the logic actually is. Therefore it is really, really easy to forget to free memory and that happens very, very frequently. Solution 1: Throw away and rewrite everything. Solution 2: Keep spaghetti as it is, replace all newed resources by smart pointers and make_shared or make_unique, let compiler yell. Of course, first write a test suite (which didn't exist before) to guarantee the same (often screwed) behaviour for all possible sets of inputs (which are not documented).
EDIT
As james said this is undefined behaviourso no promises
You could do something like this:
#include <vector>
class Base
{
public:
Base()
{
baseData = new char [1024];
}
~Base()
{
delete [] baseData;
}
private:
char* baseData;
};
class Derived : public Base
{
public:
Derived()
{
derivedData = new char[1024];
}
~Derived()
{
delete [] derivedData;
}
private:
char* derivedData;
};
int main()
{
std::vector<Base*> datablocks;
datablocks.push_back(new Base());
datablocks.push_back(new Derived());
for(unsigned int i = 0; i < datablocks.size(); ++i)
{
delete datablocks[i];
}
datablocks.clear();
return 0;
}
The data in the Derived class wont be removed here since we are calling delete on a Base* and the Base class does not declare a virtual destructor.
A lot examples could be given here. Just allocate some memory and do not free it.
A good example for this would be the following:
char* pBuffer = new char[ 1024 ]; // or something else, dynamically allocated
// do something here
// now suppose, calling f() throws
f();
// do some other things
delete[] pBuffer;
When f() throws, if the exception is not caught, delete[] will never be executed. Thus, memory leak.
This is one of the best examples why smart pointers should be used.
Another example would be - a function, returning pointer to dynamically allocated memory. The user, often, may forget to free this memory. Something like:
char
char* f()
{
return new char[ 1024 ];
}
//...
// in some other function
char* pSomething = f();
// do some stuff here and return
Imagine you're processing network data and create polymorphic "message objects" based on the data:
while (true)
{
char buf[1024];
size_t len = read_from_network(buf, 1024); // fictitious, for demonstration only
Message * p = Message::Parse(buf, len); // allocates new, dynamic, concrete object
engine.process(p);
}
The engine object may chose to store the object somewhere and use it again later, and if nobody takes care of deleting it, you have a perfect leak.
While the other answers give enough hints, some 'real world' memory leaks which I have seen in our applications.
I don't remember if this was found before or after the release, but, I guess that doesn't matter.
void f()
{
BYTE* b = NULL;
f = open a file;
while (!f.end())
{
int size = getNextRecordSize(f);
b = new BYTE;
readNextRecord(f,b);
process record;
}
delete b;
}
Bit hard to detect this. The reviewers might take it for granted that the memory is deleted properly by seeing the delete call. However, it deletes only the memory allocated for the last record. Rest is leaked.
class A
{
public:
BYTE* get()
{
allocate a new buffer, copy the someData buffer and return that.
The client is expected to delete it
};
private:
BYTE* someData;
};
void f()
{
A a;
B.initialize(a.get()); // It is so convenient to use the pointer. It is not obvious from the function name
// that the result of get has to be deleted.
}
One example I often run across in our code is in image understanding functions, where a temporary 8bit memory is allocated, and never released (yeah, I know, when you do a new, do a delete right afterwards...)
unsigned char* dataToBeUsed = new unsigned char[imgsize];
memcpy(dataToBeUsed, original, imgsize);
// use and process the data here
return value;
The allocated memory is never released -> memory leak. Windows will kill the memory when the application is exited completely, but before that within the application that memory is just lost -> leaked.
A memory leak occurs when the programmer has the memory leak of forgetting to free allocated memory :-)
linebuffer = new char[4096];
/* do things */
/* forget to free memory */
Normally, if you cause a memory leak and then exit the program, it is not harmful, since the operating system normally frees the resources allocated by the program. The problem arises when your application runs for a long period of time (for example, a service). If your program causes memory leaks, then you will run out system's memory, unless the operating system has mechanisms to avoid that; in such case, it will terminate your program.
So, be careful and eat fish: it's very good for memory :-)
To give you a real-world example, a bit of googling turned up this memory leak in 389 Directory Server (a RedHat Open Source product).
Just lose the pointer to dynamically allocated memory:
void foo()
{
int *arr = new int[100];
}

Can one deallocate memory in a destructor if they allocated memory within a private function in C++?

I am trying to define a class in the global scope which contains some dynamically-allocated arrays. When the class' constructor is called, the program does not have access to user-defined parameters read through a parameter file (i.e. the number of years in a simulation) thus it cannot allocate memory to the proper size. My idea was to allocate memory within a private function in the class, and then deallocate it using the destructor. Some example code:
class Simulation{
private:
int initial_call; //a flag used to initialize memory
double *TransferTracker;
public:
Simulation();
~Simulation();
void calc();
};
Simulation simulator; //global instance of Simulation
Simulation::Simulation()
{
initial_call = 1;
}
Simulation::~Simulation()
{
//when calling the destructor, though, the address is
//0xcccccccc and the following attempt to delete produces
//the compiler error.
delete [] TransferTracker; //see error
}
void Simulation::calc()
{
for (int i = 0; i < num_its; i++)
{
if (initial_call)
{
TransferTracker = new double [5];
//The address assigned is, for example, 0x004ce3e0
initial_call = 0;
}
}
//even if this calc function is called multiple times, I see
//that the address is still 0x004ce3e0.
}
The error I receive from the above code fragment is:
Unhandled exception at 0x5d4e57aa (msvcr100d.dll) in LRGV_SAMPLER.exe: 0xC0000005: Access
violation reading location 0xccccccc0.
This error makes sense because I checked the memory address of TransferTracker when entering the destructor. My question is, why do we lose the address when entering the destructor? It probably has something to do with the fact that simulator is global; this paradigm seems to work fine if the class was not global. I am new to object-oriented programming so any help is appreciated!
EDIT: This was basically a blunder on my part and was helped by the answers. Two problems occurred: (1) the pointers were never set to NULL, thus creating confusion on trying to delete unallocated pointers. (2) There were actually two instances of the class in my scope, which was a mistake on my part. In the final code, there will only ever be one instance. Thanks everyone!
Initialize the pointer to NULL (0)
Simulation::Simulation() : TransferTracker(NULL)
{
initial_call = 1;
}
Simulation::~Simulation()
{
//when calling the destructor, though, the address is
//0xcccccccc and the following attempt to delete produces
//the compiler error.
if(TransferTracker) delete [] TransferTracker; //see error
TransferTracker = NULL;
}
That way you can check wether or not it has been initialised when you want to delete it. It's best practice, so do it always, not only at construction
EDIT:
void Simulation::calc()
{
for (int i = 0; i < num_its; i++)
{
if (initial_call)
{
if(TransferTracker) delete [] TransferTracker;
TransferTracker = new double [5];
initial_call = 0;
}
}
}
You have to initialize the value of the instance variable TransferTracker to 0 in the constructor. The problem you're having is the destruction of the Simulation class without actually having assigned dynamic memory to TransferTracker.
Calling delete[] in the destructor with a null pointer is safe. The problem is that if you don't give a value to TransferTracker, it may have any undefined value, that will cause trouble trying to deallocate with delete[].
EDIT:
As per your edit, how do you assure that there is only one instance of the Simulation class? This has to do with if you include several .o files in your build, etc.
I suspect the cause is that your destructor is getting called when you haven't invoked the calc() function, therefore the memory hasn't been allocated yet.
You want to put in place a "guard" that will make sure that you've already allocated the memory before attempting to deallocate the memory for TransferTracker.

Can a C++ class determine whether it's on the stack or heap?

I have
class Foo {
....
}
Is there a way for Foo to be able to separate out:
function blah() {
Foo foo; // on the stack
}
and
function blah() {
Foo foo* = new Foo(); // on the heap
}
I want Foo to be able to do different things depending on whether it's allocated on the Stack or the Heap.
Edit:
Alof of people have asked me "why do this?"
The answer:
I'm using a ref-counted GC right now. However, I want to have ability to run mark & sweep too. For this, I need to tag a set of "root" pointers -- these are the pointers on the stack. Thus, for each class, I'd like to know whether they're in the stack or in the heap.
A hacky way to do it:
struct Detect {
Detect() {
int i;
check(&i);
}
private:
void check(int *i) {
int j;
if ((i < &j) == ((void*)this < (void*)&j))
std::cout << "Stack" << std::endl;
else
std::cout << "Heap" << std::endl;
}
};
If the object was created on the stack it must live somewhere in the direction of the outer functions stack variables. The heap usually grows from the other side, so that stack and heap would meet somewhere in the middle.
(There are for sure systems where this wouldn't work)
You need to actually ask us the real question(a) :-) It may be apparent to you why you think this is necessary but it almost certainly isn't. In fact, it's almost always a bad idea. In other words, why do you think you need to do this?
I usually find it's because developers want to delete or not delete the object based on where it was allocated but that's something that should usually be left to the client of your code rather than your code itself.
Update:
Now that you've clarified your reasons in the question, I apologise, you've probably found one of the few areas in which what you're asking makes sense (running your own garbage collection processes). Ideally, you'd override all the memory allocation and de-allocation operators to keep track of what is created and removed from the heap.
However, I'm not sure it's a simple matter of intercepting the new/delete for the class since there could be situations where delete is not called and, since mark/sweep relies on a reference count, you need to be able to intercept pointer assignments for it to work correctly.
Have you thought about how you're going to handle that?
The classic example:
myobject *x = new xclass();
x = 0;
will not result in a delete call.
Also, how will you detect the fact that the pointer to one of your instances is on the stack? The interception of new and delete can let you store whether the object itself is stack or heap-based but I'm at a loss as to how you tell where the pointer is going to be assigned to, especially with code like:
myobject *x1 = new xclass(); // yes, calls new.
myobject *x2 = x; // no, it doesn't.
Perhaps you may want to look into C++'s smart pointers, which go a long way toward making manual memory management obsolete. Shared pointers on their own can still suffer from problems like circular dependencies but the judicious use of weak pointers can readily solve that.
It may be that manual garbage collection is no longer required in your scenario.
(a) This is known as the X/Y problem. Many times, people will ask a question that pre-supposes a class of solution whereas a better approach would be just to describe the problem with no preconceptions of what the best solution will be.
The answer is no, there is no standard/portable way to do this. Hacks involving overloading the new operator tend to have holes. Hacks that depend on checking pointer addresses are OS specific and heap implementation specific, and may change with future versions of the OS. You may be comfortable with that, but I wouldn't build any sort of system around this behavior.
I would start looking at different ways to accomplish your goal - perhaps you can have a totally different type to serve as the "root" in your scheme, or require the users to (properly) annotate the stack allocated types as such with a special constructor.
It is possible if you compare the value of 'this' with the current value of the stack pointer. If this < sp then you have been allocated in the stack.
Try this out (using gcc in x86-64):
#include <iostream>
class A
{
public:
A()
{
int x;
asm("movq %1, %%rax;"
"cmpq %%rsp, %%rax;"
"jbe Heap;"
"movl $1,%0;"
"jmp Done;"
"Heap:"
"movl $0,%0;"
"Done:"
: "=r" (x)
: "r" (this)
);
std::cout << ( x ? " Stack " : " Heap " ) << std::endl;
}
};
class B
{
private:
A a;
};
int main()
{
A a;
A *b = new A;
A c;
B x;
B *y = new B;
return 0;
}
It should output:
Stack
Heap
Stack
Stack
Heap
A more direct, and less intrusive method would be to look up the pointer in the memory region maps (such as /proc/<pid>/maps). Each thread has a region allocated to its stack. Static and global variables will live in the .bss section, constants in a rodata or const segment, and so on.
I am not positive what you are asking, but overriding the new operator may be what you are trying to do. As the only safe way to create an object on the heap in C++ is to use the new operator, you can differentiate between objects that exist on the heap versus other forms of memory. Google "overloading new in c++" for more information.
You should, however, consider if differentiating between the two types of memory is really necessary from inside the class. Having an object behave differently depending upon where it is stored sounds like a recipe for disaster if you are not careful!
As mentioned above, you need to control how your object is allocated through overloaded new operator. Watch out for two things however, first the 'placement new' operator that initializes your object inside the memory buffer preallocated by user; second, nothing stops the user from simply casting arbitrary memory buffer into your object type:
char buf[0xff]; (Foo*)buf;
Another way is the fact that most runtimes use a bit more memory than asked when doing heap allocations. They usually place some service structure there to identify proper deallocations by pointer. You could inspect your runtime implementation for these patterns, although it will make your code really unportable, dangerous and unsupportable overkill.
Again, as mentioned above, you really are asking for solution details ("how") when you should ask about the initial problem you devised this solution for ("why").
Nope, it can't be done reliably or sensibly.
You may be able to detect when an object is allocated with new by overloading new.
But then what if the object is constructed as a class member, and the owning class is allocated on the heap?
Here's a third code example to add to the two you've got:
class blah {
Foo foo; // on the stack? Heap? Depends on where the 'blah' is allocated.
};
What about static/global objects? How would you tell them apart from stack/heap ones?
You could look at the address of the object, and use that to determine if it is within the range that defines the stack. But the stack may be resized at runtime.
So really, the best answer is that "there's a reason why mark & sweep GC's aren't used with C++".
If you want a proper garbage collector, use a different language, one which supports it.
On the other hand, most experienced C++ programmers find that the need for a garbage collector pretty much vanishes when you learn the necessary techniques for resource management (RAII).
The meta question as asked by pax is asked "why would you want to do that" you'll likely get a more informative answer.
Now assuming you're doing this for "a good reason" (perhaps just curiousity) can get this behaviour by overriding operators new and delete, but don't forget to override all 12 variants including:
new, delete, new no throw, delete no throw, new array, delete array, new array no throw, delete array no throw, placement new, placement delete, placement new array, placement delete array.
One thing you can do is put this in a base class and derive from it.
This is kind of a pain, so what different behavior did you want?
A way for MFC classes:
.H
class CTestNEW : public CObject
{
public:
bool m_bHasToBeDeleted;
__declspec(thread) static void* m_lastAllocated;
public:
#ifdef _DEBUG
static void* operator new(size_t size, LPCSTR file, int line) { return internalNew(size, file, line); }
static void operator delete(void* pData, LPCSTR file, int line) { internalDelete(pData, file, line); }
#else
static void* operator new(size_t size) { return internalNew(size); }
static void operator delete(void* pData) { internalDelete(pData); }
#endif
public:
CTestNEW();
public:
#ifdef _DEBUG
static void* internalNew(size_t size, LPCSTR file, int line)
{
CTestNEW* ret = (CTestNEW*)::operator new(size, file, line);
m_lastAllocated = ret;
return ret;
}
static void internalDelete(void* pData, LPCSTR file, int line)
{
::operator delete(pData, file, line);
}
#else
static void* internalNew(size_t size)
{
CTestNEW* ret = (CTestNEW*)::operator new(size);
return ret;
}
static void internalDelete(void* pData)
{
::operator delete(pData);
}
#endif
};
.CPP
#include "stdafx.h"
.
.
.
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
void* CTestNEW::m_lastAllocated = NULL;
CTestNEW::CTestNEW()
{
m_bHasToBeDeleted = (this == m_lastAllocated);
m_lastAllocated = NULL;
}
Overload new() for your class. This way you'll be able to tell between heap and stack allocation, but not between stack and static/global.
I would recommend using smart pointers instead. By design, the class should have data and information about class. Book-keeping tasks should be delegated outside the class.
overloading new and delete can lead to more holes than you can imagine.
To answer your question, a reliable way (assuming your aplication isn't using more thant one thread), assuming that everithing wich is not contained by your smart pointer isn't on the heap :
-> Overloading new, so that you ca store a list of all blocs allocated, with the size of each block.
-> When the constructor of your smart pointer, search in wich block your this pointer belong. If it isn't in any block, you can say it's "on the stack" (actualy, it means it's not managed by you). Otherwise, you know where and when your pointer was allocated (if you wan't to look for orphan pointers and lasily free memory, or things like that..)
It do not depend from the architechture.
There is a solution, but it forces inheritance. See Meyers, "More Effective C++", Item 27.
EDIT:
Meyers' suggestion is summarized in an article written by Ron van der Wal, which Meyers himself linked to in his blog (in this post):
Tracking heap based objects
As an alternative to the global variable
approach, Meyers presents a HeapTracked class that uses a list to keep
track of the addresses of class instances allocated off the heap, then
uses this information to determine if a particular object resides on
the heap. The implementation goes like this:
class HeapTracked {
// Class-global list of allocated addresses
typedef const void *RawAddress;
static list<RawAddress> addresses;
public:
// Nested exception class
class MissingAddress {};
// Virtual destructor to allow dynamic_cast<>; pure to make
// class HeapTracked abstract.
virtual ~HeapTracked()=0;
// Overloaded operator new and delete
static void *operator new(size_t sz)
{
void *ptr=::operator new(sz);
addresses.push_front(ptr);
return ptr;
}
static void operator delete(void *ptr)
{
// Remove ‘ptr’ from ‘addresses’
list<RawAddress>::iterator it=find(addresses.begin(),
addresses.end(), ptr);
if (it !=addresses.end()) {
addresses.erase(it);
::operator delete(ptr);
} else
throw MissingAddress();
}
// Heap check for specific object
bool isOnHeap() const
{
// Use dynamic cast to get start of object block
RawAddress ptr=dynamic_cast<RawAddress>(this);
// See if it’s in ‘addresses’
return find(addresses.begin(), addresses.end(), ptr) !=
addresses.end();
}
};
// Meyers omitted first HeapTracked:: qualifier...
list<HeapTracked::RawAddress> HeapTracked::addresses;
There is more to read on the original article: Ron van der Wal comments on this suggestion, and then demonstrates other alternative heap tracking methods.
Take a look at the program here: http://alumni.cs.ucr.edu/~saha/stuff/memaddr.html. With a few casts, it ouputs:
Address of main: 0x401090
Address of afunc: 0x401204
Stack Locations:
Stack level 1: address of stack_var: 0x28ac34
Stack level 2: address of stack_var: 0x28ac14
Start of alloca()'ed array: 0x28ac20
End of alloca()'ed array: 0x28ac3f
Data Locations:
Address of data_var: 0x402000
BSS Locations:
Address of bss_var: 0x403000
Heap Locations:
Initial end of heap: 0x20050000
New end of heap: 0x20050020
Final end of heap: 0x20050010