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:
- 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>
.
- 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){});
}