使用std :: mutex而不是boost :: mutex时出现未处理的异常 [英] Unhandled exception when using std::mutex instead of boost::mutex

查看:2802
本文介绍了使用std :: mutex而不是boost :: mutex时出现未处理的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图摆脱我的代码中的一些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().


未处理的异常在0x7721E3BE .dll)in GrabberTester.exe:0xC0000005:访问冲突读取位置0xA6A6B491。

Unhandled exception at 0x7721E3BE (ntdll.dll) in GrabberTester.exe: 0xC0000005: Access violation reading location 0xA6A6B491.

真正的项目非常复杂,提供了一个完整的工作代码示例来重现这个问题。在我真正的项目中,互斥体被用在一个共享库中,在运行时加载(但在从 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 and std::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 of boost::mutex?
  • In the shared library I'm creating threads with the boost::thread framework. Could it be that std::mutex can only be used with std::threads and is incompatible with boost::threads?

我注意到的另一件事:当我卸载动态加载的共享库,这需要一些时间。 (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:


  1. 您有一个静态互斥体(可以是静态类的成员)。

  2. doexit()代码开始清理您的静态内容。

  3. 互斥体在doexit()中被销毁


  1. You have a static mutex (could be a member of a class that is static).
  2. The doexit() code starts cleaning up your static stuff.
  3. The mutex is destroyed somewhere in doexit()
  4. 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时出现未处理的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆