🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

std::unique_ptr::reset crashes when called from destructor

Started by
9 comments, last by Bregma 4 years, 7 months ago

I probably haven't understood something very basic here and kindly ask for help. There is a problem occurring since i switched from raw pointers to std::unique_ptr.

I have a singleton i use for debug drawing of primitive shapes. It holds unique pointers to several member objects like


...
std::unique_ptr<Program> m_shaderDebug{ nullptr };
std::unique_ptr<VertexArray3D<omath::dvec3>> m_boxArray{ nullptr };
...

I get the singleton like this as a member of another drawable object O:


orf_n::DrawPrimitives &m_drawPrimitives{ orf_n::DrawPrimitives::getInstance() };

Somewhere in O i call the setup:


m_drawPrimitives.setupDebugDrawing();

That sets the above members of the singleton like for example:


Icosphere is{ omath::dvec3{ 0.5, 0.5, 0.5 }, 2 };
m_sphereArray = std::make_unique<VertexArray3D<omath::dvec3>>( is.getVertices(), 0, true );
m_sphereIndices = std::make_unique<IndexBuffer>( is.getIndices() );

and a flag m_allSetup that setup has taken place.

Now, when i call the singleton's cleanup method that simply does


if( m_allSetup ) {
	m_boxArray.reset();
	m_shaderDebug.reset();
	m_boxIndices.reset();
	....

the program exits fine.

If i wait for the singleton's destructor to call the cleanup method, the program segfaults. The debugger tells me the pointers holdvalid objects of the respective type at that time.

I probably haven't got something basic here.

Let me know if you need more code.

 

Advertisement

Apologies if any of this is too obvious, but here are some possible things to try:

- Look into the 'static destruction order fiasco' (which may or may not be a factor here).

- What do the objects in question do in their destructors? Do they rely on other state that's already been altered by the time the destructors run? (The 'static order' issue could be a factor here as well.)

- Can you use log output, comment out code selectively, examine the crash information, and/or step through the various destructors in the debugger to try to narrow down where the problem is occurring?

Perfectly ok ?

Quote

- What do the objects in question do in their destructors? Do they rely on other state that's already been altered by the time the destructors run? (The 'static order' issue could be a factor here as well.)

Yeah, the destructors wrote to a logfile, holding a mutex while doing so. I outcommented the writing and it does not segfault to me any more. I believe the problem was bad design and is solved. Thanks !
 

14 hours ago, Green_Baron said:

I have a singleton

Found the problem.

Stephen M. Webb
Professional Free Software Developer

lol, well, to my excuse, part of that roots in a time when all that was very new to me (about a year and a half ago) and i read about and sought help in design patterns and all that. And i don't want to throw it all over now because other code would break. I think, one day a simple bunch of globals functions in an own namespace with a simple logic of "is available or not" will be the more flexible solution. And i am always open for any hints on how to improve, be it only a link ...

:-)

 

5 hours ago, Bregma said:

Found the problem.

Like always: Use the right tool for the right purpose. Singletons are quiete useful in some cases. I use one for my memory management system and I have seen other memory management systems that did it quite similar.

However, I agree that singletons can cause some serious problems. It's one of many C++ 'features' that tend to be overused. It often provides a fast solution to get around function interfaces. It removes the need for careful class, function and program design. If you get unlucky, this might backfire when the singleton is already an integral part of your program. :(

Greetings

 

9 hours ago, DerTroll said:

Like always: Use the right tool for the right purpose. Singletons are quiete useful in some cases. I use one for my memory management system and I have seen other memory management systems that did it quite similar.

Agreed, but I have yet to see a situation where singletons are the right tool. 

The other issue is that generally, people don’t use a singleton as a singleton. 
 

Singletons are meant to enforce singularity of cardinality at a class level. You literally cannot create more than one instance of the class. 

But most people use a singleton pattern to enforce singularity of *access*, and it’s almost always just a lazy way of avoiding passing the correct dependencies to an object instance. 
 

 

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

Just to be funny/mean, i could say everything was fine as long as i controlled the data with new and delete and raw pointers, the problem started when introducing smart pointers. Are the smart pointers to blame ?

Now people will say that the problem didn't start, it just became evident, but before this gets eschatological (that an English word ?) i admit: there is a design problem and i will eradicate it. I mean eliminate, purge, do away with, dispose of and remove. I promise.

Seriously, thanks for help and insight !

1 hour ago, Green_Baron said:

i admit: there is a design problem and i will eradicate it. I mean eliminate, purge, do away with, dispose of and remove. I promise.

Just to clarify that: My answer wasn't targeting you in any way. To be honest, I didn't even fully read your post, since the way code is formatted on my smartphone is horrible. I just responded to @Bregma answer, cause it sounds like "Singletons are always" bad and I don't agree with that. In my opinion, It is just often overused in a way it turns into pain than an actual good solution for a problem. The same goes for OOP, unsigned ints ( ;)) and probably a lot of other options C++ provides. Worst thing: Most of the time there is no clear indication about which approach is the best but people get quite religious about dos and don'ts.
 

8 hours ago, ChaosEngine said:

Agreed, but I have yet to see a situation where singletons are the right tool.  

You can say that about many other design patterns too. But what is the right tool? They are one possible tool. If it is the best is often opinion based since the weighting on the pros and cons is also opinion-based. As I said before, I think a memory manager is a good example where it can make sense to use a singleton. You can surely program one without using a singleton, but the only other solutions I know/have thought of are hard to work with. If you can show me a good alternative to get rid of the singleton without other extra annoyances, I would appreciate it (actually I have a pretty raw idea floating through my mind, maybe I can figure out something by myself) because singletons are a pain in terms of unit testing.
 

However, for everybody interested, here is a quite interesting StackOverflow question where you get all the pros and cons and different opinions to make up your own:

https://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

It was closed because: Surprise, surprise --- > Opinion based.

 

Greetings

 

3 hours ago, Green_Baron said:

eschatological

That is a fine, fine English word. Nicely played.

One of the reasons why singletons are something to avoid is because they introduce the latent hazard of non-deterministic destruction order.  That's not a problem for languages with non-deterministic destruction (for example, Java and Python), but it is fraught with peril for a language that requires deterministic destruction.  This is the problem you encountered. You have had your epiphany and you are now saved.

The good thing is we learn 100 times as much from one mistake as from 100 successes.  I bet you'll never use a singleton in new code again.

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement