• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Jan2go

Passing shared_ptr between modules

9 posts in this topic

I have a singleton class (EventManager) in a static lib that gets linked by both the .exe and a dynmic lib. Events are passed around as std::shared_ptr<IEvent>. The EventManager stores all queued events in a std::list and pops them out after handling them. This works fine as long as all events were added from the exe. If I add events from inside the DLL, pop_front throws an exception at the last event that was added from inside the DLL. It doesn't matter whether the DLL adds one event or 1000, only the one that was added last throws the exception.

This is the exception:

Debug Assertion Failed!

Program: ...ts\visual studio 2013\Projects\QueueTest\Debug\DynamicLib.dll
File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
Line: 1424

Expression: _pFirstBlock == pHead

I'm using the Visual Studio 2012 with compiler for this.

I know that you should not deallocate memory in any module other than the one that allocate the memory. However, from what I've read std::shared_ptr can be used to avoid this problem as it contains a pointer to the deleter for the memory.

 

I attached a sample project with this problem to this post.

 

Any ideas on how I can get the EventManager to work with events coming from a DLL?

0

Share this post


Link to post
Share on other sites

Agree with Sean.  I probably undersold the idea of designing a clear ownership policy.  Even if you're not dealing with cross-module issues, it's a good practice to always spend some time thinking about your program's ownership policy.  A well understood and well chosen policy can make a whole host of problems go away, or not even appear to begin with.

0

Share this post


Link to post
Share on other sites
According to the debugger all function pointers inside the shared_ptr go to the DLL, including those that are related to deleting stuff (at least by name). Also, all but the last event get destroyed correctly inside the DLL so I think that the deleter is set correctly.

Using the /MD flag works, however I would prefer a solution that works with /MT. I tried to switch to /MD a while back and for some reason (can't remember why, I think it was a library that I'm using) didn't get the project to work with /MD.

About the unique_ptr, the compiler doesn't let me declare a std::list of unique_ptrs in the EventManager class.
0

Share this post


Link to post
Share on other sites

About the unique_ptr, the compiler doesn't let me declare a std::list of unique_ptrs in the EventManager class.


That somewhat surprises me. Posting the errors may be helpful; it's definitely legal to have a unique_ptr in a list. http://goo.gl/6bl6Fi

That said, std::list is Satan's data structure; consider using a deque or even a vector instead.
0

Share this post


Link to post
Share on other sites

This is just speculation, but it is possible that most of the events appear to get deleted fine due to implementation defined behavior of the runtime's allocator.  For example, if every piece of allocated memory is part of a larger block that is predictably aligned, then on delete, the deallocator usually only needs to jump to the beginning of that memory's aligned block and fiddle with some book keeping information.  This will work just fine even when technically using the wrong allocator, as long as the code is the same.  But as soon as the deallocator notices that it freed the last piece of memory in a block, it might want to clean up the whole block.  And to do this, it might need to check some other memory that is unique to that particular allocator (such as a list of memory blocks that the allocator is managing).  If this block of memory wasn't actually allocated by the allocator currently doing the deallocation, things get confused really fast.

 

This might be the kind of thing that is happening when you delete the very last event.  All deletes might be wrong, but the debug runtime only notices that fact on the last delete, when it tries to clean up a block.

 

Also keep in mind that your events are not the only thing being allocated and deallocated across dll boundaries.  Every call to events.push_back() is going to use the default list allocator to allocate a linked list node, and every call to events.pop_front() will use that allocator to deallocate the node.  But this is almost definitely a stateless static allocator.  Since you statically link your event manager to both your exe and dll, the allocator used is going to depend on which module the calls to Queue() and HandleEvents() comes from.  Calling Queue() from the dll is going to allocate from the dll, and calling HandleEvents() from the exe is going to deallocate from the exe.  No amount of shared_ptr intelligence will protect against this, because this is completely independent of the memory allocated for events.  Stateful allocators would solve this (at the cost of a little overhead), but have only been possible since C++11, and I'm not sure what VS2012's support of these is like.

 

Without stateful allocators, you pretty much need to figure out a way to guarantee that all manipulations to a container happen within a single module.  In your case, you might actually try making your event manager library a dll also, instead of a static library.  That way, all manipulations to the events list is guaranteed to happen within that dll, regardless of where the call to Queue() and HandleEvents() comes from.

0

Share this post


Link to post
Share on other sites

That somewhat surprises me. Posting the errors may be helpful; it's definitely legal to have a unique_ptr in a list. http://goo.gl/6bl6Fi

That said, std::list is Satan's data structure; consider using a deque or even a vector instead.

 This is the error message. It was caused by a call to EventManager's copy constructor, so no actual problem with list<unique_ptr>. smile.png

Error 1 error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0 617 1 StaticLib

 
 

Also keep in mind that your events are not the only thing being allocated and deallocated across dll boundaries.  Every call to events.push_back() is going to use the default list allocator to allocate a linked list node, and every call to events.pop_front() will use that allocator to deallocate the node.

To be honest, I didn't took that into consideration until now. I tried it with a std::vector (small enough to avoid reallocation from within the DLL) and deleting object from the vector (thereby destroying them) works without problems. However a heap corruption occurs when the program exists, so there is still something that gets broken in the process.

 

I guess I'll try the /MD switch again, hopefully I can get it to work this time. biggrin.png

0

Share this post


Link to post
Share on other sites

This is the error message. It was caused by a call to EventManager's copy constructor, so no actual problem with list.
Error 1 error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0 617 1 StaticLib


Ah, yeah. The lack of a copy constructor in unique_ptr should cause list to not have a copy constructor which should cause EventManager to not have a copy constructor and everything just work until you actually try to explicitly copy EventManager. Older compilers lacked this feature, including Visual Studio 2012 (which you appear to be using). You might consider upgrading to 2013.
0

Share this post


Link to post
Share on other sites

Older compilers lacked this feature, including Visual Studio 2012 (which you appear to be using). You might consider upgrading to 2013.


I wish that would be the only feature that is not supported in VS 2012. biggrin.png From what I've read there will most likely be a new version of VS later this year; I'll probably update the project to the new compiler then (hopefully removing lots of #ifdef _MSC_VER >= 1700 smile.png).
0

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  
Followers 0