【问题标题】:unlock of unowned mutex windows debug build解锁无主的互斥体窗口调试版本
【发布时间】:2020-12-14 10:56:11
【问题描述】:

我正在尝试将现有的 Windows 代码移植到适用于 Windows 和 Linux 的通用代码。 将 CRITICAL_SECTION 替换为 std::mutex。代码失败并出现错误:“unlock of unowned mutex”。这只发生在调试版本而不是发布版本。

这里是观察行为的示例代码:

#include "pch.h"
#include <iostream>
#include <mutex>


static std::mutex g_suCxioAccessLock;

int main()
{
    std::unique_lock<std::mutex> locker(g_suCxioAccessLock);
    std::cout << "Hello World!\n"; 
    g_suCxioAccessLock.unlock();
}

你能帮我理解为什么它在调试构建中失败

【问题讨论】:

  • 使用locker.unlock()。您将互斥锁交给了unique_lock。用它来解锁它(或者只是让它离开作用域;也就是说,毕竟是基于作用域的锁定点)。

标签: c++ windows mutex


【解决方案1】:

std::unique_lock 的要点是在构造时锁定互斥体,并在 unique_lock 超出范围时解锁它。您可以使用unique_lock::unlock() 获取unique_lock 以尽早解锁互斥锁,尽管这并不常见;否则你应该让它自己解锁。就您的代码而言,它使用g_suCxioAccessLock.unlock() 手动解锁互斥锁,然后unique_lockmain() 返回后再次尝试解锁。

【讨论】:

  • 为什么它不会在 Release 构建中失败?
  • 在无法正常工作的意义上它确实“失败”了。但是 Debug 构建包含额外的检查和错误消息,可帮助您找到代码中的错误,例如此检查告诉您正在解锁未锁定的互斥锁。
【解决方案2】:

当它超出范围时,锁已经解锁了互斥锁。您的代码有效地尝试解锁互斥锁两次,但std::mutex::unlock

解锁互斥锁。

互斥锁必须被当前执行线程锁定,否则行为未定义。

您的代码具有未定义的行为。任何事情都可能发生,编译器只是很好地使您的代码在调试构建中导致运行时错误。在发布版本中,mutex 可能会被编译器完全删除,因为草率地说,编译器“知道”UB 不属于已编译的程序。只解锁一次互斥锁。

【讨论】:

  • @hythis “GCC 不遵循规范”是什么意思?当规范说它是未定义的行为时,GCC 可以根据规范做任何事情。抛出异常是一种非常友好的未定义行为
  • @hythis 您不能两次解锁互斥锁。尝试这样做是未定义的行为
【解决方案3】:

g_suCxioAccessLock.unlock(); 将解锁两次,您可以将其移除。

【讨论】:

    猜你喜欢
    • 2018-05-23
    • 2015-01-16
    • 2022-07-31
    • 2014-10-09
    • 1970-01-01
    • 2015-09-26
    • 2021-12-23
    • 2010-11-22
    相关资源
    最近更新 更多