使用std :: mutex而不是boost :: mutex时出现未处理的异常

问题描述 投票:10回答:4

我试图摆脱代码中的一些boost依赖项,而是使用新的C ++ 11特性(Visual Studio 2013)。

在我的一个组件中,我使用boost::mutexboost::lock_guard<boost::mutex>,一切正常。当我使用std::mutexstd::lock_guard<std::mutex>代替时,从main()返回时出现以下错误。

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

真正的项目非常复杂,因此难以提供完整的工作代码示例来重现此问题。在我的真实项目中,互斥体用在一个共享库中,该库在运行时加载(但是当我从main()返回时应该已经卸载了它)。

我的问题是:

  • boost::mutexstd::mutex的设计是否完全相同?
  • 如果没有,有什么区别?使用std::mutex而不是boost::mutex时,我需要记住什么?
  • 在共享库中,我正在使用boost::thread框架创建线程。可能是std::mutex只能与std::threads一起使用并且与boost::threads不兼容吗?

编辑:

我注意到的另一件事是:当我卸载动态加载的共享库时,这需要一些时间。 (DLL访问硬件,干净地关闭所有内容需要一些时间)。当我切换到std::mutex然而它看起来几乎可以立即卸载DLL,但程序然后在从main()返回时崩溃。我的印象是std::mutex的问题特别是在DLL的上下文中。

编辑2:

应用程序和DLL都是使用v120工具集在Debug配置中新建的,并与运行时库(/ MTd)静态链接。

编辑3:

下面你可以找到callstack。例外似乎来自驱动程序中的某个地方。只是偶然我发现它与我使用的互斥锁的实现有关。

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

c++11 mutex openni unhandled-exception boost-mutex
4个回答
5
投票

最有可能的问题是静态init地狱,我最近经历了几乎同样的事情。这是下来的事情:

  1. 你有一个静态互斥(可能是一个静态的类的成员)。
  2. doexit()代码开始清理静态内容。
  3. 互斥体在doexit()的某处被破坏
  4. 有些东西在被破坏之后使用互斥锁,经常在析构函数中使用。

问题是你并不真正知道静态对象的破坏顺序。所以如果你有:

static std::mutex staticMutex;

void someFunction()
{
    std::unique_lock<std::mutex> lock(staticMutex);
    doSomethingAwesome();
}

....

StaticObjA::~StaticObjA()
{
    someFunction();
}

然后,当调用~SpaticObjA()时,您的静态互斥锁CAN已被删除/销毁/ deadbeef。当对象在不同的​​编译单元中定义时(即在不同的文件中定义),问题会恶化。

我的解决建议是尝试减少对静态对象的依赖,你可以尝试使用一个静态对象来处理其他所有内容的构造/破坏,这样就可以控制事件的顺序。或者根本就不要使用静力学。


1
投票

当我的代码试图锁定两次相同的互斥锁时,我遇到了类似的问题:一个函数获得了锁,然后调用另一个试图获取同一个全局/静态互斥锁的函数。

mutex queueMutex;

void f1()
{
    lock_guard<mutex> guard(queueMutex);
    f2();
}

void f2()
{
    lock_guard<mutex> guard(queueMutex); //unhandled exception!
}

0
投票

我添加了同样的问题,解决了什么......全手动清理+重建!验证是否删除了所有.obj,.dll,.lib文件。


0
投票

不要使用Mircosoft的std :: mutex(或recursive_mutex,...)!我有类似的问题。我正在使用VS2012。

如果在dll中使用std :: mutex,则不能卸载此dll。因为你得到一个未定义的行为。 (在我的情况下0xC0000005:访问冲突读取位置....)。或者你无法卸载DLL。 (可能“?运行时?”会增加加载计数器.Double FreeLibrary()卸载dll)

© www.soinside.com 2019 - 2024. All rights reserved.