Sign in to follow this  
dr4cula

Smart Pointers Confusion

Recommended Posts

dr4cula    360

Hello,

 

I was playing around with smart pointers in C++ (VS2010) and encountered some unexpected behavior. Best explained by this code snippet:

// allocate the memory
Test* dynamic = new Test;
 
// take over the ownership
std::unique_ptr<Test> takeOver(dynamic);
 
// wait for ENTER to continue
std::getchar();
 
// clear the memory
takeOver.reset();
 
// shouldn't this cause a crash?
dynamic->reference(1);
 
// oddly enough the following line doesn't cause an immediate crash either
// if I press ENTER next though, it crashes and the debugger says that it might be due to heap corruption
//delete dynamic;
 
std::getchar();

Output I get from the application is the following:

 

Constructing test...
 
Destroying test...
accessing func for owner 1
 
From what I can gather, the memory does get freed since a second delete call causes heap corruption. However, why is the original pointer still valid and prints out the result from that function call?
 
Any help would greatly be appreciated and thanks in advance!

Share this post


Link to post
Share on other sites
dr4cula    360

Calling a member function on a deleted object is undefined behavior, which often means a crash, but can really do anything at all including succeeding. In this case I'm guessing that your member function doesn't actually use any member variables so doesn't actually access any deleted memory.

 

Ah, of course. Indeed, as soon as I added a member variable, the function returned junk values. Just to be certain though, I allocated memory for an int in the constructor, then in the destructor deleted it and set the pointer to NULL and then had the original pointer query that member function that returned the variable's value and the application crashed as expected. Thanks for the quick reply!

Share this post


Link to post
Share on other sites

Even if does did use member variables, why should the code bother wasting processing power clearing or zero-ing out the deleted memory? (though in debug mode it might)

It could be "deleted' but the bytes don't have to change that quickly if nothing else happens to use that now-available piece of memory; the bytes could possibly still even return the correct result without crashing, even after being deleted. Undefined behavior.

 

Many a hard-to-track bug result from manually managing memory or mixing up pointers. mellow.png

That's one of the things smart pointers aim to prevent.

 

A safer way to create a smart pointer is to use the std::make_ functions:

std::shared_ptr<Type> myPtr = std::make_shared<Type>(3.14f, "Type's parameters");
std::unique_ptr<Type> myPtr = std::make_unique<Type>(...);

If your compiler doesn't have std::make_unique yet, here's a placeholder until it gets it:

//std::make_unique implementation (it was forgotten in the C++11 standard, and will be added later).
//Once it's added, I can just remove this from here.
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
	return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

You already have std::make_shared.

 

Aside from a small behind-the-scenes optimization, the std::make_ functions are safer.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this