What happens if a C/C++ API returns a raw pointer from an internally used shared_ptr, then the shared_ptr gets "deleted"? Is the raw pointer still valid? How can the API developer clean up the raw pointer when it's not in their control anymore?
As an example:
MyClass* thisReturnsAPtr()
{
std::shared_ptr<MyClass> aSharedPtr = std::make_shared<MyClass>(MyClass);
return aSharedPtr.get();
}
If there are no other shared_ptr around anymore that still hold a reference to the object and, thus, keep the object alive, then the object will be destroyed, the memory freed, and any still existing pointer that pointed to that object will become a dangling pointer.
In your example above, the pointer returned by the function thisReturnsAPtr is guaranteed to be an invalid pointer…
It can sometimes be useful to think of smart pointers as a delayed delete mechanism. What I mean by that is that if you allocate a class and give it to a smart pointer you are basically asking the smart pointer class to delete that pointer sometime in the future. For a shared_ptr that time in the future is when no more shared_ptrs exist for it.
Applying this to your code, you create a shared_ptr. You then return the raw pointer. Then your function ends and the only shared_ptr to that pointer gets destroyed and so the underlying class is deleted.
This makes your question "If I new a class and delete it then return the original pointer what happens". Which is a lot easier to answer and the answer to that is "badness". There are many answers to this question on stack overflow - such as C++ delete - It deletes my objects but I can still access the data?
"What happens to a raw pointer if it's shared_ptr is deleted?" - Nothing. It just becomes invalid to subsequently use that pointer.
"a C/C++ API returns a raw pointer from an internally used shared_ptr, then the shared_ptr gets "deleted"? Is the raw pointer still valid?"
No. It is not valid to then use the raw pointer. And the raw pointer does not change (to nullptr) to indicate that the pointed-to object has been deleted.
It is your responsibility to ensure, that if something like that happens, you do not use the raw pointer after it has been invalidated. How you do that is up to you - the language doesn't care/help you.
Using the raw pointer after the object it points to has been deleted, is Undefined Behaviour.
My question is that what are the various ways in which get() member from the shared_ptr class can be used? And why can't we use delete to delete it?
If you had a function taking a raw pointer
void f(T *t); // non-owning pointer
And you had a smart pointer to a T object, you could pass it to that function by using get()
std::shared_ptr<T> sp{new T}; // or unique_ptr
//f(sp); // no good, type mismatch
f(sp.get()); // passes the raw pointer instead
APIs taking raw pointers are common, and still useful. I'd suggest you watch this part of Herb Sutter's talk from CppCon 2014, and probably the parts around it.
You should not attempt to delete this pointer, the smart pointer classes assume you will not do anything like that, and will still free the managed object in their own destructors when the time comes (after all, how would it know you deleted it?).
The smart pointer's job is to manage the object and delete it at the right time, if you want to manually manage the lifetime of the object (not usually recommended) then use a raw pointer.
If you do want to assume ownership of a unique_ptr you can do so by calling release().
Usually you would use get() when you need to pass a raw pointer to an API that accepts such a pointer.
The shared_ptr class manages the ownership of the pointer, so it will automatically delete the owned memory when the lifetime of the smart pointer ends. If you try to delete the memory yourself then when the shared_ptr tries to deallocate you will wind up with undefined behavior.
I'd like to wrap raw pointer member to some smart pointer to prevent deleting inside a developing class. Owner of the object under pointer is outside of class. So, looks like boost::shared_ptr and std::auto_ptr does not fit. The following is a reduced example:
class Foo {
boost::weak_ptr<Bar> m_bar;
public:
void setBar(const Bar *bar) { // bar created on heap
m_bar = bar; // naturally compilation error
}
};
Of course, it induces compilation error. What is a correct way to initialize weak_ptr from a raw pointer (if exist)?
You can't do that, you can only create a weak_ptr out of a shared_ptr or another weak_ptr.
So the idea would be that the owner of the pointer hold a shared_ptr instead of a raw pointer, and everything should be ok.
The only way to do it is by getting hold of a shared_ptr or weak_ptr that owns the pointer, otherwise the weak_ptr has no way to find the existing owner in order to share ownership with it.
The only way to get a shared_ptr from a raw pointer that is already owned by another shared_ptr is if Bar derives from enable_shared_from_this<Bar>, then you can do
m_bar = bar->shared_from_this();
The purpose of a weak pointer is to be unable to use the raw pointer if it had been deleted. However, if you have a raw pointer, the weak pointer has no way to know that it was deleted. Instead, you must have a shared_ptr somewhere which "owns" the raw pointer. Then you can create a weak_ptr which references the shared_ptr.
When the shared_ptr goes out of scope and is the last "strong" smart pointer, it will automatically delete the raw pointer. Then, when you try to lock the weak_ptr, it will see that there is no "strong" pointer remaining and therefore the object does not exist.
Everything you've said seems perfectly reasonable, except for one thing:
void setBar(const Bar *bar)
This shouldn't take a raw pointer. It should take a weak_ptr ideally, or possibly a shared_ptr if you have some compelling argument.
The actual owner of the object in question should construct the weak_ptr and than call setBar with that. This preserves the ownership semantics. It looks like what you're doing is having the owning object take a raw pointer and pass that to setBar. This creates a semantic gap in the ownership of the object.
Pass shared pointer instead of raw pointer, and create your weak pointer from that shared pointer. This is really the only way if owner of the pointer is outside of a class.
Is it appropriate for a class to return a a raw pointer in a "create" method and take a raw pointer argument in its "destroy" method? The aforementioned class stores the pointer in a container and finds/deletes the specified object through the destroy method.
Or should I be using smart pointers? If I understand correctly, smart pointers indicate ownership, but the class is solely responsible for both creation and destruction of the object.
The question is: Can you programatically describe the acquire/release behaviour that the code should have? If yes, i.e. the behaviour isn't a series of unique events without any pattern, then you can write a handle class that implements this behaviour. Even more, this handle class will be able to guarantee the behaviour, which is what smart pointers are all about. It's not just about correctness of code, but about extended guarantees that make it easier to write correct code.
Also, smart pointers don't always indicate ownership, though they do in most cases. There is also a distinction between shared ownership (shared_ptr) and exclusive ownership (auto_ptr, unique_ptr). Then, there is e.g. a mere reference without ownership (weak_ptr).
To me, it sounds like you might want to return a shared_ptr with an according deleter. The factory can then e.g. keep a weak_ptr to retain some access to the according objects, while the shared_ptr guarantees correct cleanup. Make sure you regularly purge expired weak_ptrs from the factories internals though.
In no case would I return a raw pointer. The question this bears is: What should the caller do with it when they are done? Call delete? Call some specific destroy() function? Both of these are better handled by a smart pointer. Also, if the factory retains ownership and reserves itself the right to discard the object at any time, how is the one holding a raw pointer informed about the fact that this pointer will become invalid? A simple answer would be to use a smart pointer that gets notified, like e.g. weak_ptr.
I have a method that has a few pointers as parameters. This method can be called with either named pointers from the callee or dynamically create a pointer to a new object and pass it in as an argument directly as the method is being called.
myClass *myPtr = new myClass(...);
myMethod(myPtr);
Verus
myMethod(new myClass(...));
The problem is that if both of these are valid options, how does one properly free the passed in pointer? Deleting myPtr within myMethod will cause a crash if myPtr is ever accessed again within the program. If I don't delete myPtr, the second option will cause a memory leak if it is used. There are benefits for using both options so both shouldn't break the program.
Aside from using STL, what are some solutions to this problem? Would I have to implement my own garbage collector?
I would say, in this case caller should be responsible for freeing the object. You can consider various options, simplest is:
myClass myInstance = myClass; // or myClass(arg1, arg2, ...)
// and the pass it to your method like this:
myMethod(&myInstance);
You could also consider some smart pointer options like std::tr1::shared_ptr or something from boost.
UPDATE: If your method should be able to get NULL-pointer as its argument, there's no problem at all:
// this is your method declaration:
void myMethod(const myClass *myPtr);
// in your tests or wherever in your code you can call it like
myClass myInstance = myClass; // or myClass(arg1, arg2, ...)
myMethod(&myInstance);
// or like this:
myMethod(NULL);
// for as long as your method has something like this in it:
if (myPtr)
myPtr->someMethod();
You can use a smart pointer for that, like shared_ptr from boost.
If not you need to state clearly who owns the object. If you are going to take over the ownership or leave it to the caller.
If you leave it to the caller, using the form function(new whatever()) wouldn't be a good idea, but the leak would be responsibility of the caller.
If you intent to take over the ownership, creating a sink method, choosing a proper name would be a good idea, of course you'd need to delete the objects by yourself once you are finished.
First thing, you need to assign ownership of the object: you need to have a consistent strategy (and enforced!) as to "who" has the right to delete an object. Once this is clearly established, you shouldn't have the problem you are running into.
Some strategies:
Object is leased: ownership is retained by lender
Object is given: ownership is transferred
Second, for tracking usage of an object, you need an infrastructure such as "smart pointers". Here you have 2 categories to care about:
Object is "singly referenced" i.e. only one "user"
Object is "multi referenced" i.e. more than one "user" at one point in time
For (1), the "tracking information" is the pointer itself whereas in (2) you need more infrastructure.
You should use some sort of smart pointer.
For this simple case ever auto_ptr is fine but in general you should use scoped_ptr or shared_ptr.
If you have some unexplained phobia against STL or boost, you can always pull your own smart pointer class with relative ease (if you don't require super exception safety).
This is a all about ownership.
You need to decide who has ownership (or is there shared ownership).
Basically passing pointers is a very bad idea and NOT very C++ like (this is basically a C interface as there is no concept of ownership). In a C++ program you should define your interfaces (functions) with a very clear sense of ownership transfer.
You have a couple of options.
The function does not have ownership and can not be NULL.
In this case you should pass by reference
The function does not have ownership but may be NULL.
Pass as a pointer and add comments that ownership is not being transferred. This is the worst situation and you should try and avoid this as the semantics are not clearly expressed by the code.
The function takes ownership.
In this case I would suggest using std::auto_ptr as it explicitly indicates that ownership is being transferred to the function.
The function shares ownership.
In this case some form of shared smart pointer like boost::shared_ptr or std::tr1::shared_ptr
In your case I would suggest 1 or 2 depending on the situation.
It is obviously that the function can not delete the pointer as it sometimes may not have ownership. Thus the ownership remains on the side of the caller. So the caller must call the delete as appropriate. Hopefully via some smart pointer mechanism.
You need to decide on the ownership, either:
Caller owns object: object is LOANED to function, Caller is responsible for allocation and deletion.
Function owns object: object is DONATED to function, Caller is responsible for allocation, callee (function) is responsible for deletion.
Use a reference counting via a shared pointer to avoid the problem.
( 2 is ugly because it means that different code is responsible for allocation and deletion, but that might be the correct solution for your case - it also means making copies of the argument if the caller wants to keep the object).
Both of these are valid options in the c++ syntax sense, but I'd argue that the second option is bad software design in almost all cases, and allowing both options in one function might even be bad software design in all cases.
Either the calling class creates the object, calls the method, and deletes the object,
or the calling class creates the object, calls the methon, and expects the method to delete the object.
I see no good reason why both options should be considered reasonable in one method call. It should be clear from documentation or comments which version the method uses, and it is then up to the developer to use that method, or suffer the consequences.
The common behavior is for functions neither to create nor to destroy objects. However, there are functions that do. Common jargon is "sources and sinks". A very useful convention, if you're not using more versatile smart pointers, is to use std::auto_ptr<T> for both sources and sinks. A "source" function returns the object created as an auto_ptr<T>, whereas a sink takes an argument of type auto_ptr<T>.
The benefit is that even if you forget the return value of a source function, you won't have a memory leak. At the end of the statement, the returned auto_ptr destroys the object returned. And similarly, it is obvious that the argument passed in to a void sink(auto_ptr<T> unreferenced) { } will be destroyed before sink returns.
The memory should be freed by its owner. Usually, the owner is the entity that allocated the memory, but in some cases you may allow ownership to be transferred.
void foo() {
myClass* p = new myClass(); // foo owns the pointer, so foo should release it again
}
void foo() {
boost::shared_ptr<myClass> p = new myClass(); // foo allocates the memory, but *transfers* ownership to the smart pointer. The smart pointer is now responsible for freeing the object. (This is true for all types of smart pointers, including boost::scoped_ptr, std::auto_ptr or the C++0x std::unique_ptr.
}
void foo() {
ScopedMyClass x; // ScopedMyClass is some class wrapper which *internally* calls `new myClass`, and so owns the allocation and is responsible for freeing it before the end of the wrapper class' lifetime.
}
In your case specifically, if myMethod doesn't allocate the memory, then it should not free the memory either.
As for how to handle this:
myMethod(new myClass(...));
Just don't do that. If you allocate memory, you need to take ownership of it. Store the pointer first, so you can delete the memory:
myClass* p = new myClass(...);
myMethod(p);
delete p;
or even better, *don't dynamically allocate the object in the first place, eliminating the question of ownership:
myMethod(myClass(...));
I can't comment yet but .. While I would normally argue strongly for the 'creator owns it' paradigm (can you really prove anything else correct?) , I think that the insistence on having the
myMethod(new myClass(...));
usage pretty much requires ownership to be transferred. Perhaps it would be prudent to ask what you're attempting to accomplish with this usage, and could it be handled in another way? Like an overload that takes a reference to the temporary instead of a pointer?
myMethod(myClass& a) { return myMethod(&a); }
myMethod(myClass(...))
Well, I suppose I'll add my little stone to the edifice... though I am not sure it will even be read.
This is a matter of ownership of the memory, it is the role of your interface to convey this meaning: "Will this method take ownership or not".
To better express ownership, it is usually bad to use raw pointers. The STL has the bastard auto_ptr which is better suited to the task (I am waiting for the upcoming unique_ptr rather impatiently there).
For a method, there are several ways to accept parameters:
// Value
void method(T);
// Reference
void method(T&);
// Pointer
void method(T*);
// Smart Pointer
void method(std::auto_ptr<T>);
I skipped the cv-qualification bit because it's irrelevant there.
The point is that out of these 4 solutions, the intent is clear:
Value / Reference / Pointer: the caller is responsible for the memory
auto_ptr the method takes ownership of the memory, this means that the caller cannot use the variable afterward
std::auto_ptr myT = std::auto_ptr(new T());
method(myT);
assert(myT.get() == 0); // myT does not hold anything any longer!
Of course, that's why auto_ptr is a wild beast out there, since it does not respect the convention that a copying an object leaves the copied object apparently unchanged: normally all the public methods should give the same result before and after, reference counting being a corner case here if you expose it.
So, your interface should be clearer if whether or not the caller should expect the method to take ownership or not, a simple way is to use overloading.
void method(T*); // do something
void method(std::auto_ptr<T> p)
{
method(p.get());
}
Easy enough, you are now clear on who handles the memory!
With the same reasonment you can also use this overloading trick to automatically check a pointer for nullity.
void method(T&); // do something
void method(T* p)
{
if (p) method(*p); else throw NullPointer("method");
}
But I would avoid abusing the trick, you'll end up with thousands of methods.
So just remember: ownership semantic is best expressed in CODE rather than in comments.
Which you will immediately mix with Use RAII to manage resources which means here that you should never allocate memory to a raw pointer: use a smart pointer to express ownership of the resource, and a raw pointer to point to existing objects you do not own (and that might possibly be null, otherwise a reference is better ;) ).