问题描述
我试图摆脱我的代码中的一些boost依赖,而是使用新的C ++ 11功能(Visual Studio 2013)。
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).
的我的组件我使用 boost :: mutex
和 boost :: lock_guard< boost :: mutex>
精细。当我使用 std :: mutex
和 std :: lock_guard< std :: mutex>
从 main()
返回时出现以下错误。
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()
.
真正的项目非常复杂,提供了一个完整的工作代码示例来重现这个问题。在我真正的项目中,互斥体被用在一个共享库中,在运行时加载(但在从 main()
返回时,应该已经卸载了。
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()
).
我的问题是:
- :mutex 和
std :: mutex
设计为完全相同? - 差异?使用
std :: mutex
而不是boost :: mutex
时,我需要注意什么? - 在共享库中,我使用
boost :: thread
框架创建线程。可能是std :: mutex
只能与std :: thread
一起使用,与boost :: thread
s?
- Are
boost::mutex
andstd::mutex
designed to behave absolutely the same? - If not, what are the differences? What do I need to keep in mind when using
std::mutex
instead ofboost::mutex
? - In the shared library I'm creating threads with the
boost::thread
framework. Could it be thatstd::mutex
can only be used withstd::thread
s and is incompatible withboost::thread
s?
我注意到的另一件事:当我卸载动态加载的共享库,这需要一些时间。 (DLL访问硬件,它需要一些时间关闭一切干净整洁)。当我切换到 std :: mutex
然而它看起来像DLL可以几乎立即卸载,但程序然后崩溃从 main()
。我有一个印象, std :: mutex
的问题是在DLL的上下文中。
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.
应用程序和DLL都是使用v120工具集在Debug配置中新建的,并且与运行时库(/ MTd)静态链接。
Both the application and the DLL are freshly built in Debug configuration with the v120 toolset and statically linked with the runtime library (/MTd).
下面你可以找到callstack。这个异常似乎来自驱动程序中的某处。只是偶然我发现它与我使用的互斥体的实现。
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()
编辑4:
也许这是OpenNI2 SDK中的一个错误,仅在这些非常具体的条件下观察。所以我添加了openni标签到这个问题。但仍然的问题仍然是:它为什么它工作与 boost :: mutex
但不是与 std :: mutex
?
推荐答案
问题最有可能是static init hell,我最近经历了几乎相同的事情。下面是发生了什么:
The problem most likely is static init hell, I recently went through almost this same thing. Here is what is going down:
- 您有一个静态互斥体(可以是静态类的成员)。
- doexit()代码开始清理您的静态内容。
- 互斥体在doexit()中被销毁
-
- You have a static mutex (could be a member of a class that is static).
- The doexit() code starts cleaning up your static stuff.
- The mutex is destroyed somewhere in doexit()
- Something uses the mutex after it has been destroyed, often times in a destructor.
问题是,你真的不知道静态对象的销毁顺序。所以如果你有:
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();
}
然后你的静态互斥量已经被删除/销毁/ deadbeef当〜StaticObjA )被调用。当对象被定义在不同的编译单元(即在不同的文件中定义)时,这个问题会加剧。
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.
这篇关于使用std :: mutex而不是boost :: mutex时出现未处理的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!