I try to get rid of some of the boost dependencies in my code and instead use the new C++11 features (Visual Studio 2013).
In one of my components I used boost::mutex
together with boost::lock_guard<boost::mutex>
and everything worked fine. When I use std::mutex
together with std::lock_guard<std::mutex>
instead, I get the following error when returning from main()
.
Unhandled exception at 0x7721E3BE (ntdll.dll) in GrabberTester.exe: 0xC0000005: Access violation reading location 0xA6A6B491.
The real project is quite complex and it's therefore difficult to provide a full working code example to reproduce this problem. In my real project the mutexes are used in a shared library which is loaded at runtime (but which should already be unloaded by the time I'm returning from main()
).
My questions are:
boost::mutex
and std::mutex
designed to behave absolutely the same?std::mutex
instead of boost::mutex
?boost::thread
framework. Could it be that std::mutex
can only be used with std::thread
s and is incompatible with boost::thread
s?One more thing I noticed: When I unload the dynamically loaded shared library this takes some time. (The DLL accesses hardware and it takes some time to shut everything down cleanly). When I switch to std::mutex
however it looks like the DLL can be unloaded almost immediately, but the program then crashes when returning from main()
. I have the impression that the problem with std::mutex
is specifically in the context of a DLL.
Both the application and the DLL are freshly built in Debug configuration with the v120 toolset and statically linked with the runtime library (/MTd).
Below you can find the callstack. The exception seems to come from somewhere in the driver. Only by accident I figured out that it has to do with which implementation of mutex I use.
ntdll.dll!7721e3be()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!7721e023()
kernel32.dll!76b014ad()
msvcr100.dll!71b0016a()
PS1080.dll!oniDriverDestroy() Line 29
OpenNI2.dll!oni::implementation::DeviceDriver::~DeviceDriver() Line 95
OpenNI2.dll!oni::implementation::Context::shutdown() Line 324
OpenNi2Grabber.dll!openni::OpenNI::shutdown() Line 2108
OpenNi2Grabber.dll!GrabberSingletonImpl::~GrabberSingletonImpl() Line 46
OpenNi2Grabber.dll!`GrabberSingletonImpl::getInstance'::`2'::`dynamic atexit destructor for 'inst''()
OpenNi2Grabber.dll!doexit(int code, int quick, int retcaller) Line 628
OpenNi2Grabber.dll!_cexit() Line 448
OpenNi2Grabber.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 169
OpenNi2Grabber.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 399
OpenNi2Grabber.dll!_DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 340
ntdll.dll!7722b990()
ntdll.dll!77249bad()
ntdll.dll!77249a4f()
kernel32.dll!76b079ed()
GrabberTester.exe!__crtExitProcess(int status) Line 776
GrabberTester.exe!doexit(int code, int quick, int retcaller) Line 678
GrabberTester.exe!exit(int code) Line 417
GrabberTester.exe!__tmainCRTStartup() Line 264
GrabberTester.exe!mainCRTStartup() Line 165
kernel32.dll!76b0338a()
ntdll.dll!7722bf32()
ntdll.dll!7722bf05()
Maybe this is a bug in the OpenNI2 SDK which can be observed only under these very specific conditions. So I added the openni tag to this question. But still the question remains: why does it work with boost::mutex
but not with std::mutex
?
I had a similar problem when my code attempted to lock twice the same mutex: a function acquired the lock then called another function that was trying to acquire a lock on the same global/static mutex.
mutex queueMutex;
void f1()
{
lock_guard<mutex> guard(queueMutex);
f2();
}
void f2()
{
lock_guard<mutex> guard(queueMutex); //unhandled exception!
}
The problem most likely is static init hell, I recently went through almost this same thing. Here is what is going down:
The problem is that you don't really know the order of destruction for static objects. So if you have:
static std::mutex staticMutex;
void someFunction()
{
std::unique_lock<std::mutex> lock(staticMutex);
doSomethingAwesome();
}
....
StaticObjA::~StaticObjA()
{
someFunction();
}
Then your static mutex CAN already be deleted/destroyed/deadbeef when ~StaticObjA() is invoked. The problem is exacerbated when the objects are defined in different compilation units (i.e. defined in different files).
My recommendation for solving is to try to reduce your dependence on static objects, you could try to have 1 static object that takes care of construction/destruction of everything else, so that you can control the order of events. Or just don't use statics at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With