Sending the same pointer into two different shared_ptr's is bad, it causes double deallocation, like thus:
int* p = new int;
std::shared_ptr<int> p1(p);
std::shared_ptr<int> p2(p); // BAD
You can accomplish the same purpose with std::enable_shared_from_this:
class Good: public std::enable_shared_from_this<Good>
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
int main()
{
std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
}
But that still doesn't protect against:
class Good: public std::enable_shared_from_this<Good>
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
int main()
{
Good* p = new Good;
std::shared_ptr<Good> gp3(p);
std::shared_ptr<Good> gp4(p); // BAD
}
which could become a problem if you have code like this:
void Function(std::shared_ptr<Good> p)
{
std::cout << p.use_count() << '\n';
}
int main()
{
Good* p = new Good;
std::shared_ptr<Good> p1(p);
Function(p); // BAD
}
Why would I use a regular pointer when there's smart pointers? Because in performance critical code (or for convenience) the overhead of shared_ptr or weak_ptr is undesirable.
To prevent this mistake, I've done:
class CResource : public shared_ptr<Good>
{
public:
CResource()
{
}
CResource(std::shared_ptr<CBaseControl> c)
: CResource(c)
{
}
private:
CResource(CBaseControl* p)
{
}
};
void Function(CResource p)
{
std::cout << p.use_count() << '\n';
}
int main()
{
Good* p = new Good;
CResource p1(std::shared_ptr<Good>(p));
Function(p); // Error
}
This would cause the compiler to error if anyone tries to call Function with a pointer instead of a shared_ptr. It doesn't prevent someone from declaring void Function(std::shared_ptr p) though, but I think that's unlikely.
Is this still bad? Is there a better way of doing this?
The solution is simple: never have a raw pointer own memory in the first place. This pattern:
int* p = new int;
std::shared_ptr<int> p1(p);
std::shared_ptr<int> p2(p); // BAD
Simply shouldn’t exist. Eradicate it from your code base. The only places where new is legitimate in C++11 is as an argument to a constructor call to a smart pointer (or in very low level stuff).
I.e. have code like this:
std::shared_ptr<int> p1(new int);
Or better yet (no naked new involved any longer):
auto p1 = std::make_shared<int>();
Note that it’s fine to use raw pointers in code (but I’d question even that in most C++ code I’ve seen). But if you use raw pointers, don’t let them own the memory. Either point to automatic storage (no resource management necessary) or use a unique_ptr and access the raw pointer via its get member function.
This example doesn't even compile:
void Function(std::shared_ptr<Good> p)
{
std::cout << p.use_count() << '\n';
}
int main()
{
Good* p = new Good;
std::shared_ptr<Good> p1(p);
Function(p); // BAD
}
shared_ptr has an explicit constructor precisely to stop that happening.
To make that compile you need to write:
Function( std::shared_ptr<Good>(p) );
which is pretty obviously wrong, and if someone's going to make that mistake they're just as likely to do:
Function( CResource(std::shared_ptr<Good>(p)) );
So why have you bothered to write CResource? What does it add?
To expand on Konrad Rudolph's excellent answer:
The answer to your question of how to avoid problems is to follow the RAII idiom, but follow it fully.
We'll ignore the example that doesn't even compile and look at the one above it:
Good* p = new Good;
std::shared_ptr<Good> gp3(p);
std::shared_ptr<Good> gp4(p); // BAD
That code fails to follow the RAII idiom. You acquire a resource:
Good* p = new Good;
But do not initialize an RAII type. BAD.
Then you initialize an object with some existing resource:
std::shared_ptr<Good> gp3(p);
This is also BAD. You should initialize an RAII type at the same time as acquiring the resource, not separately (not even only separated by one line.)
Then you repeat the same error:
std::shared_ptr<Good> gp4(p); // BAD
You've marked this line as "BAD" but actually the previous two lines were just as bad. The third line will cause undefined behaviour, but the first two lines allowed that error to creep in, when it should have been made more difficult. If you never had a Good* hanging around then you couldn't have used it to initialize gp4, you'd have needed to say shared_ptr<Good> gp4(gp3.get()) which is so obviously wrong noone will do it.
The rule is pretty simple: Don't take a raw pointer and put it in a shared_ptr. A raw pointer you didn't allocate is not resource acquisition so don't use it for initialization. The same applies inside Function, it should not take the raw pointer and use it to initialize a shared_ptr that takes ownership of the type.
This is C++, so it's not possible to protect against all the wrong ways to write code, you can't prevent sufficiently motivated idiots from shooting themselves in the foot, but all the guidelines and tools are there to prevent it, if you follow the guidelines.
Whn you have an interface that forces you to transfer ownership by passing a raw pointer, try to replace the interface so it uses a unique_ptr for ownership transfer, or if it's totally impossible to do that then try to wrap the interface in a safer version using unique_ptr for ownership transfer, and only as a last resort, use the dangerous interface but document it very explicitly that ownership is transferred.
Related
Suppose I have a method that defines a shared_ptr. After the method finishes, the shared_ptr will also be deleted. In the interim I have another member that uses that shared_ptr. So I would like to extend the lifetime of the shared_ptr past the initial method.
void initial_method(int input)
{
std::shared_ptr<int> a { std::make_shared<int>(input) };
some_delayed_method(a);
}
Is it possible to manually increase the reference count of a by one in this example?
some_delayed_method() is like a detachment and is referring to a at a time after the initial_method() has returned.
Since you can't call some_delayed_method without a shared_ptr to the object and any shared_ptr to the object extends its lifetime, there is nothing you need to do.
If some_delayed_method saves the pointer in some external data structure, and this pointer will later be used, you should use shared_ptr for that.
class X
{
public:
void initial_method(int input)
{
std::shared_ptr<int> a { std::make_shared<int>(input) };
some_delayed_method(a);
}
void some_delayed_method(const std::shared_ptr<int>& a)
{
use_later = a;
}
private:
std::shared_ptr<int> use_later;
}
This way, the reference count will be handled automatically.
You may insist on using a raw pointer to save the data for later:
void some_delayed_method(const std::shared_ptr<int>& a)
{
use_later = a.get();
}
...
int* use_later;
This is not a proper way to save the data. To make it work (or appear to work), you have to do some hack. For example, make another reference to the data, and leak it:
void some_delayed_method(const std::shared_ptr<int>& a)
{
use_later = a.get();
new std::shared_ptr<int>(a); // horrible hack; please never do it! but it works...
}
This hack leaks the allocated std::shared_ptr so it can never be deleted, thus its refcount is not decremented and the allocated int is leaked.
I want to create an instance of a class using new, but I want to convert to reference for further usage other than using pointer. Currently I am using this line Foo& rf = *f; to convert explicitly, it seems a bit silly. Any better and more elegant ways to create a reference variable and referring a new created instance?
Here are some code to show what I am doing,
class Foo{
public:
Foo(){
}
void printValue() {
cout << "This is Foo object " << endl;
}
};
int main() {
Foo* f = new Foo();
Foo& rf = *f;
rf.printValue();
f -> printValue();
}
You can write this:
Foo* foo = new Foo();
Foo& fooRef = *foo;
in one line:
Foo& fooRef = *new Foo();
But, be aware, you should delete your allocated memory later anyway:
delete &fooRef;
I do not suggest you write code in this way, to avoid memory leaks. Look into this answer for further details. Choose smart pointers or containers when it possible.
... convert to reference for further usage other than using pointer.
I prefer references (and avoid pointers) deep in my code. Mostly because a nullptr can have special meaning (that a reference will not) that needs some thought to confirm, the next time I review the code.
My solution is to new the bigger-than-automatic-memory object to get a pointer at the appropriate level for lifetime. I then invoke the using methods or functions with the dereferenced pointer. This keeps the pointer (at the lifetime start, such as main) as is, and later still available for the delete.
// bigData used many places
void use1_of_Data (BigData_t& bigData, Small_t& sd) {
//... do something with data
}
void use2_of_Data (BigData_t& bigData, Small_t& sd) {
//... do something with data
}
//...
void use3_of_Data (BigData_t& bigData, Small_t& sd) {
//... do something with data
}
int main(int argc, char* argv[])
{
// ...
BigData_t* bd = new BigDta_t; // (sizeof(BigData_t) > autovar space)
Small_t sd;
{
assert(nullptr != bd);
// note - bd lasts the lifetime of program
use1_of_Data (*bd, sd);
use2_of_Data (*bd, sd);
//...
use3_of_Data (*bd, sd);
}
// what's new'd in main, is deleted in main
delete bd;
}
As others have said, if the Foo instance's non-heap contents aren't so large that the Foo instance itself needs to be allocated on the heap, it is better to just use the stack:
Foo foo;
foo.printValue();
However, if it does need to be allocated on the heap for some reason, then it's dangerous to hold the only reference to it in an ordinary pointer, since if an exception gets thrown by any code, it will never be deallocated. In fact, most modern C++ guidelines advise not using ordinary pointers to own data for this reason:
Foo * fooPtr = new Foo();
doSomething(); // If an exception is thrown here, the Foo never gets deallocated!
Foo& foo = *fooPtr;
foo.printValue(); // If printValue throws an exception, the Foo never gets deallocated!
delete foo;
If you aren't familiar with this sort of problem, I suggest googling RAII ("Resource Acquisition Is Initialization") which is an crucial concept to understand when programming in C++.
An easy way to implement RAII in a case like this is through use of a smart pointer (std::shared_ptr or std::unique_ptr).
An extra reference variable can still be helpful to avoid having to use the arrow operator to call functions on the smartpointer. I disagree with some other answerers who don't see value in also binding a local reference to a value already held in a local pointer. I prefer to use references whenever possible, since when I use a reference, I can be sure that the reference isn't null (references should always refer to actual objects), while when I use a pointer (even a smart pointer) I must always be careful that my code correctly handles the case where the pointer is null. When the pointer initialization occurs close to the pointer's use, this may not be a big deal, but when they are separated, it can become hard to trace through the code to be sure the pointer can't be null. A reference makes this self-documenting.
I think that it is often useful to first ensure that a pointer or smart pointer value can't be null, and then to bind a local reference to the pointed-to value, since I can then use the reference freely without having to worry at each use about the possibility of it being null:
std::unique_ptr<Foo> fooPtr = std::make_unique<Foo>(/* Foo constructor args go here */);
doSomething(); // Now if an exception thrown here, Foo gets deallocated.
Foo& foo = *fooPtr; // We know the pointer is not null here (it just
// got returned from make_unique which
// didn't throw a bad_alloc exception) so it's
// safe to bind a reference to it here.
// Also, this reference has lifetime less than the
// smart pointer, so will never outlive it.
// .. many lines of code later ..
foo.printValue(); // No need to worry about null here.
// If exception thrown here, the unwinding of the stack
// causes fooPtr to deallocate Foo.
// No need to call delete here.
// fooPtr will automatically deallocate Foo when it goes out of scope.
If we speak about elegance, may I suggest you to use a shared_ptr?
#include <iostream>
#include <memory>
using namespace std;
class Foo{
public:
Foo(){
}
void printValue() {
cout << "This is Foo object " << endl;
}
};
int main(int argc, char *argv[])
{
Foo* f = new Foo();
std::shared_ptr<Foo> mySharedPtr(f);
f->printValue();
mySharedPtr.get()->printValue();
return 0;
}
I know that it's possible to say delete this in C++ whenever you allocated something with new, using traditional pointers. In fact, I also know that it's good practice IF you handle it carefully. Can I have an object say delete this if it's being held by an std::shared_ptr? And that ought to call the destructor, right? To give you an idea, I'm making a game where a ship can shoot missiles, and I'd like to have the missiles delete themselves.
No, it's not safe, the lifetime of the object is determined by holders of shared_ptr, so the object itself cannot decide whether it wants to die or not. If you do that, you'll get double
delete when last shared_ptr dies. The only solution I can offer is "rethink your design" (you probably don't need shared_ptr in the first place, and missiles probably could be values or pooled objects).
For a missile to delete itself it must own itself, or at the very least, share ownership of itself with others. Since you say that there is a shared_ptr to the missile, I am assuming that you already have multiple objects sharing ownership of the missile.
It is possible for the missile to hold a shared_ptr to itself, and thus share in the ownership of itself. However this will always create a cyclic ownership pattern: For as long as the missile's shared_ptr data member refers to itself, the reference count can never drop to zero, and thus the missile is leaked.
You could have an external object or event tell the missile to delete itself but then I'm not sure what the point is. In order to tell the missile to delete itself, that communication should take place via a shared_ptr, and then the delete isn't really going to happen until that shared_ptr lets go of the missile.
Yes, it is possible. No, I don't think it is a good idea. It looks prone to memory leakage to me and doesn't actually add value. But for the curious, here is how you would do it:
#include <iostream>
#include <memory>
class missile
: public std::enable_shared_from_this<missile>
{
std::shared_ptr<missile> self_;
public:
missile()
{}
~missile() {std::cout << "~missile()\n";}
void set_yourself()
{
self_ = shared_from_this();
}
void delete_yourself()
{
if (self_)
self_.reset();
}
};
int main()
{
try
{
std::shared_ptr<missile> m = std::make_shared<missile>();
m->set_yourself();
std::weak_ptr<missile> wp = m;
std::cout << "before first reset()\n";
m.reset();
std::cout << "after first reset()\n";
// missile leaked here
m = wp.lock();
m->delete_yourself();
std::cout << "before second reset()\n";
m.reset(); // missile deleted here
std::cout << "after second reset()\n";
}
catch (const std::exception& e)
{
std::cout << e.what() << '\n';
}
}
I know I'm late to the show but I ran into wanting to do this myself just now and realized that it is "kind-of-possible" but you need to take care of a few things.
Howard's answer is on the right track but misses the mark as you shouldn't leave construction of the original shared_ptr to the client. This is what opens up the risk of memory leaks. Instead you should encapsulate the construction and only allow weak pointers.
Here is an example:
class Missile{
private:
Missile(...){ }; // No external construction allowed
Missile(const Missile&) = delete; // Copying not allowed
void operator = (const Missile&) = delete; // -||-
std::shared_ptr<Missile> m_self;
public:
template<typename... Args>
static MissilePtr makeMissile(Args... args){
auto that = std::make_shared<Misile>(args...);
that.m_self = that; // that holds a reference to itself (ref count = 2)
return that; // 'that' is destroyed and ref-count reaches 1.
}
void die(){
m_self.reset();
}
...
};
typedef std::weak_ptr<Missile> MissilePtr;
void useMissile(MissilePtr ptr){
auto missile = ptr.lock(); // Now ptr cannot be deleted until missile goes out of scope
missile->die(); // m_self looses the reference but 'missile' still holds a reference
missile->whatever(); // Completely valid. Will not invoke UB
} // Exiting the scope will make the data in missile be deleted.
Calling die() will result in semantically the same effect as delete this with the added benefit that all MissilePtr that are referring to the deleted object will be expired. Also if any of the MissilePtr are used for accessing this then the deletion will be delayed until the temporary std::shared_ptr used for the access is destroyed saving you life-time headaches.
However you must make sure that you always keep at least one MissilePtr around and at some point call die() otherwise you will end up with a memory leak. Just like you would with a normal pointer.
This question is quite old, but I had a similar issue (in this case a "listener" object that had to manage its own lifecycle while still being able to share weak pointers), and googling around did not provide a solution for me, so I am sharing the solution I found, assuming that:
The object manages it's own lifecycle, and hence will never share a
share_ptr, but a weak_ptr (if you need shared_ptr's a similar
solution + use_shared_from_this could do it).
It is a bad idea to break RAII, and hence we will not do it: what we
adress here is the issue of having a shared_ptr owned by an object
itself, as containing a member share_ptr leads to double call to
the object destruction and normally a crash (or at least undefined
behaviour), as the destructor is called twice (once at normal
object destruction and a second one when destroying the self
contained shared_ptr member).
Code:
#include <memory>
#include <stdio.h>
using std::shared_ptr;
using std::weak_ptr;
class A {
struct D {
bool deleted = false;
void operator()(A *p) {
printf("[deleter (%s)]\n", p, deleted ? "ignored":"deleted");
if(!deleted) delete p;
}
};
public: shared_ptr<A> $ptr = shared_ptr<A>(this, D());
public: ~A() {
std::get_deleter<A::D>($ptr)->deleted = true;
}
public: weak_ptr<A> ptr() { return $ptr; }
};
void test() {
A a;
printf("count: %d\n", a.ptr().lock().use_count());
printf("count: %d\n", a.ptr().use_count());
}
int main(int argc, char *argv[]) {
puts("+++ main");
test();
puts("--- main");
}
Output:
$ g++ -std=c++11 -o test test.cpp && ./test
+++ main
count: 2
count: 1
[deleter (ignored)]
--- main
The shared_ptr deleter should never get called for an object allocated in stack, so when it does at normal object destruction, it just bypasses the delete (we got to this point because the default object destructor was already called).
Couldn't figure out how to word the question accurately, so here's an example:
Given this function prototype:
void Foo(myClass* bar);
I want to prevent this usage:
Foo(new myClass());
and instead require a previously created object:
myClass* bar = NULL;
bar = new myClass();
Foo(bar);
or
myClass bar;
Foo(&bar);
Thanks.
EDIT
Here's a clarified example:
void Mouse::SetImage(BITMAP* image, int focusX, int focusY) {
if(_image) {
set_mouse_sprite(NULL);
set_mouse_sprite_focus(0, 0);
show_mouse(NULL);
destroy_bitmap(_image);
_image = NULL;
}
if(image) {
_image = create_bitmap(image->w, image->h);
clear_bitmap(_image);
blit(image, _image, 0, 0, 0, 0, image->w, image->h);
}
if(image == NULL) {
focusX = 0;
focusY = 0;
}
_focusX = focusX;
_focusY = focusY;
_dirtyImage = true;
}
Whatever image the user passes in gets copied to the object's image.
If I deallocate the passed in image after copying it and the image is used elsewhere in the program it will crash the program with an access violation.
If they allocate the storage in-line and I don't deallocated it, a memory leak occurs. The problem is compounded if they call the SetImage method multiple times over the course of the running program.
Comments about using alternative libraries or on the Allegro Library itself will be ignored, I already know it's horrible. I don't have a choice.
Your design needs to make a choice. Either take ownership and delete it, or don't take ownership. Either way, it's up to the user to know how to use your function. They either need to know that your function will destroy the image (and maybe pass their own copy as needed), or they need to be smart enough to manage their own resources.
Typically, you don't want to steal ownership away just to delete it. So I would not delete anything. If someone is silly enough to lose the ability to delete the image they pass, that's not this functions problem. In other words, you should try to protect against Murphy, but forget about protecting against Machiavelli.
That said, raw pointer use is bad! Poor C++ code is marked by manual resource management and resource issues. You should have a wrapper around an image, that will delete the image in the destructor. That way you can never leak, even if an exception is thrown. Provide it with a reset() method which discards it's old image resource and gets a new one.
It sounds like you want shared ownership, so you'll want a reference counted resource wrapper. The issue is then solved: if someone does an "inline" allocation, it'll be put into the shared pointer and then deleted automatically when it's done. (And even better is to have an explicit constructor so someone has to know they'll be sharing the resource.)
This is done in a smart pointer called shared_ptr. Boost has one, TR1 has one, and C++0x has one. Just give it a custom deleted (one that frees the image), and you never worry about resource management again.
This should be done with all resources. The concept here is Scoped-bound Resource Management (SBRM); that a resource is managed automatically by taking advantage of the lifetime rules of automatic (stack) variables. It's known alos as it's original but uglier name Resource-Acquisition Is Initialization (RAII). Do some research into this area and you'll find your code is easier and cleaner.
It cannot be done without changing the type of the parameter. You could change it to:
void Foo(myClass*& bar);
Because a non-const reference can only be bound to an lvalue:
void foo(int*&);
int main(void)
{
int *i = 0;
int j;
foo(i); // well-formed
foo(&j); // ill-formed
foo(new int); // ill-formed
}
However, this disallows taking the address of an lvalue. You can of course do the simple:
int main(void)
{
int j;
int* pj = &j;
foo(pj); // well-formed
}
And it works. But I don't know why you'd want to do any of this.
The above solution would allow you to modify the argument (because it's a reference). If you wanted to enforce const within the function, you could make a utility like this:
template <typename T>
class require_lvalue
{
public:
require_lvalue(T& pX) :
mX(pX)
{}
const T& get(void) const
{
return mX;
}
operator const T&(void) const
{
return get();
}
private:
// non-copy-assignable
require_lvalue& operator=(const require_lvalue&);
const T& mX;
};
void foo(require_lvalue<int*>);
Same result, except you have a const-reference within the function.
Note that MSVC has a bug, and accepts this:
foo(new int);
in both cases, even though it shouldn't. (It does not accept new int(), however.)
It's impossible to have such a distinction of usage. And in all the cases it's a valid parameter. I really can't understand why you need this...
So don't use pointers... use (lvalue) references:
void Foo(myClass& bar);
Doesn't this solve your task?
But I anyway recommend something like std::auto_ptr for such cases.
#include <iostream>
void test(int *& ptr)
{
std::cout << *ptr << std::endl;
}
int main()
{
/* NEXT LINE WILL FAIL */
// test(new int(5));
int *b = new int(5);
test(b);
delete b;
return 0;
}
C or C++ does not give you the luxury of determining where the memory was allocated, that come into your function's parameters. If you want better safety then program in .NET.
If you want to make it safer, than just completely change your function signature to accept an auto pointer. that way the semantics become crystal clear, and there should be no confusion as to whom or what owns the memory.
Can boost::shared_ptr release the stored pointer without deleting it?
I can see no release function exists in the documentation, also in the FAQ is explained why it does not provide release function, something like that the release can not be done on pointers that are not unique. My pointers are unique. How can I release my pointers ?
Or which boost smart pointer class to use that will allow me releasing of the pointer ?
I hope that you won't say use auto_ptr :)
Don't. Boost's FAQ entry:
Q. Why doesn't shared_ptr provide a release() function?
A. shared_ptr cannot give away ownership unless it's unique() because the other copy will still destroy the object.
Consider:
shared_ptr<int> a(new int);
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
int * p = a.release();
// Who owns p now? b will still call delete on it in its destructor.
Furthermore, the pointer returned by release() would be difficult to deallocate reliably, as the source shared_ptr could have been created with a custom deleter.
So, this would be safe in case it's the only shared_ptr instance pointing to your object (when unique() returns true) and the object doesn't require a special deleter. I'd still question your design, if you used such a .release() function.
You could use fake deleter. Then pointers will not be deleted actually.
struct NullDeleter {template<typename T> void operator()(T*) {} };
// pp of type some_t defined somewhere
boost::shared_ptr<some_t> x(pp, NullDeleter() );
Kids, don't do this at home:
// set smarty to point to nothing
// returns old(smarty.get())
// caller is responsible for the returned pointer (careful)
template <typename T>
T* release (shared_ptr<T>& smarty) {
// sanity check:
assert (smarty.unique());
// only one owner (please don't play games with weak_ptr in another thread)
// would want to check the total count (shared+weak) here
// save the pointer:
T *raw = &*smarty;
// at this point smarty owns raw, can't return it
try {
// an exception here would be quite unpleasant
// now smash smarty:
new (&smarty) shared_ptr<T> ();
// REALLY: don't do it!
// the behaviour is not defined!
// in practice: at least a memory leak!
} catch (...) {
// there is no shared_ptr<T> in smarty zombie now
// can't fix it at this point:
// the only fix would be to retry, and it would probably throw again
// sorry, can't do anything
abort ();
}
// smarty is a fresh shared_ptr<T> that doesn't own raw
// at this point, nobody owns raw, can return it
return raw;
}
Now, is there a way to check if total count of owners for the ref count is > 1?
You need to use a deleter that you can request not to delete the underlying pointer.
See this answer (which has been marked as a duplicate of this question) for more information.
To let the pointer point to nothing again, you can call shared_ptr::reset().
However, this will delete the object pointed to when your pointer is the last reference to the object. This, however, is exactly the desired behaviour of the smart pointer in the first place.
If you just want a reference that does not hold the object alive, you can create a boost::weak_ptr (see boost documentation). A weak_ptr holds a reference to the object but does not add to the reference count, so the object gets deleted when only weak references exist.
The basis of sharing is trust. If some instance in your program needs to release the raw pointer, it is almost for sure that shared_ptr is the wrong type.
However, recently I wanted to do this too, as I needed to deallocate from a different process-heap. In the end I was taught that my older decision to use some std::shared_ptr was not thought-out.
I just routinely used this type for cleanup. But the pointer was just duplicated on a few places. Actually I needed a std::unique_ptr, which (suprise) has a release function.
Forgive them for they know not what they do.
This example works with boost::shared_ptr and msvs std::shared_ptr without memory leaks!
template <template <typename> class TSharedPtr, typename Type>
Type * release_shared(TSharedPtr<Type> & ptr)
{
//! this struct mimics the data of std:shared_ptr ( or boost::shared_ptr )
struct SharedVoidPtr
{
struct RefCounter
{
long _Uses;
long _Weaks;
};
void * ptr;
RefCounter * refC;
SharedVoidPtr()
{
ptr = refC = nullptr;
}
~SharedVoidPtr()
{
delete refC;
}
};
assert( ptr.unique() );
Type * t = ptr.get();
SharedVoidPtr sp; // create dummy shared_ptr
TSharedPtr<Type> * spPtr = (TSharedPtr<Type>*)( &sp );
spPtr->swap(ptr); // swap the contents
ptr.reset();
// now the xxx::shared_ptr is empy and
// SharedVoidPtr releases the raw poiter but deletes the underlying counter data
return t;
}
You can delete the shared pointer, which seems much the same to me. If pointers are always unique, then std::auto_ptr<> is a good choice. Bear in mind that unique pointers can't be used in STL containers, since operations on them do a lot of copying and temporary duplication.
I'm not entirely sure if your question is about achieving this, but if you want behaviour from a shared_ptr, where, if you release the value from one shared_ptr, all the other shared pointers to the same value become a nullptr, then you can put a unique_ptr in a shared_ptr to achieve that behaviour.
void print(std::string name, std::shared_ptr<std::unique_ptr<int>>& ptr)
{
if(ptr == nullptr || *ptr == nullptr)
{
std::cout << name << " points to nullptr" << std::endl;
}
else
{
std::cout << name << " points to value " << *(*ptr) << std::endl;
}
}
int main()
{
std::shared_ptr<std::unique_ptr<int>> original;
original = std::make_shared<std::unique_ptr<int>>(std::make_unique<int>(50));
std::shared_ptr<std::unique_ptr<int>> shared_original = original;
std::shared_ptr<std::unique_ptr<int>> thief = nullptr;
print(std::string("original"), original);
print(std::string("shared_original"), shared_original);
print(std::string("thief"), thief);
thief = std::make_shared<std::unique_ptr<int>>(original->release());
print(std::string("original"), original);
print(std::string("shared_original"), shared_original);
print(std::string("thief"), thief);
return 0;
}
Output:
original points to value 50
shared_original points to value 50
thief points to nullptr
original points to nullptr
shared_original points to nullptr
thief points to value 50
This behaviour allows you to share a resource (like an array), then later reuse that resource while invalidating all the shared references to this resource.
Here's a hack that might work. I wouldn't recommend it unless you're in a real bind.
template<typename T>
T * release_shared(std::shared_ptr<T> & shared)
{
static std::vector<std::shared_ptr<T> > graveyard;
graveyard.push_back(shared);
shared.reset();
return graveyard.back().get();
}
If your pointers are indeed unique do use std::unique_ptr or boost::scoped_ptr if the former is not available for your compiler. Otherwise consider combining the use of boost::shared_ptr with boost::weak_ptr. Check out the Boost documentation for details.
I am using Poco::HTTPRequestHandlerFactory which expects to return a raw HTTPRequestHandler*, the Poco framework deletes the handler once the request finishes.
Also using DI Sauce project to create the controllers, however the Injector returns shared_ptr which I cannot return directly, and returning handler.get() is no good either since the as soon as this function returns the shared_ptr goes out of scope and deletes then handler before its executed, so here is a reasonable (I think) reason to have a .release() method. I ended up creating a HTTPRequestHandlerWrapper class as follows :-
class HTTPRequestHandlerWrapper : public HTTPRequestHandler {
private:
sauce::shared_ptr<HTTPRequestHandler> _handler;
public:
HTTPRequestHandlerWrapper(sauce::shared_ptr<HTTPRequestHandler> handler) {
_handler = handler;
}
virtual void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) {
return _handler->handleRequest(request, response);
}
};
and then the factory would
HTTPRequestHandler* HttpHandlerFactory::createRequestHandler(const HTTPServerRequest& request) {
URI uri = URI(request.getURI());
auto path = uri.getPath();
auto method = request.getMethod();
sauce::shared_ptr<HTTPRequestHandler> handler = _injector->get<HTTPRequestHandler>(method + ":" + path);
return new HTTPRequestHandlerWrapper(handler);
}
which satisfied both Sauce and Poco and works nicely.
I needed to pass a pointer through async handlers and to keep the self-destruct behavior in case of failure but the final API expected a raw pointer, so I made this function to release from a single shared_ptr:
#include <memory>
template<typename T>
T * release(std::shared_ptr<T> & ptr)
{
struct { void operator()(T *) {} } NoDelete;
T * t = nullptr;
if (ptr.use_count() == 1)
{
t = ptr.get();
ptr.template reset<T>(nullptr, NoDelete);
}
return t;
}
If ptr.use_count() != 1 you shall get a nullptr instead.
Do note that, from cppreference (bold emphasis mine):
If use_count returns 1, there are no other owners. (The deprecated member function unique() is provided for this use case.) In multithreaded environment, this does not imply that the object is safe to modify because accesses to the managed object by former shared owners may not have completed, and because new shared owners may be introduced concurrently, such as by std::weak_ptr::lock.
Easy solution, increase the reference and then leak the shared_pointer.
boost::shared_ptr<MyType> shared_pointer_to_instance(new MyType());
new boost::shared_ptr<MyType>();
MyType * raw_pointer = shared_pointer_to_instance.get()
This will clearly cause a memory leak of both the shared_ptr and the MyType *