Boost::mutex, pthread_mutex_destroy失败的调试建议
boost::mutex, pthread_mutex_destroy failed - debug suggestions?
在静态类中有几个锁(boost::mutex),但是当程序退出时,互斥锁的析构函数中的pthread_mutex_destroy失败(boost中有一个断言检查这一点)。
据我所知,pthread_mutex_destroy只会在两种情况下失败。
[EBUSY] The implementation has detected an attempt to destroy the object referenced by mutex while it is locked or referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread.
[EINVAL] The value specified by mutex is invalid.
当我在GDB中运行并打印锁时,我看到它已解锁。不幸的是,我在GDB中打印errno时遇到了麻烦。
#3 0x000000000044a2c6 in ~mutex (this=0x847840, __in_chrg=<value optimized out>) at /usr/include/boost/thread/pthread/mutex.hpp:47
47 BOOST_VERIFY(!pthread_mutex_destroy(&m));
(gdb) p m
$1 = {__data = {__lock = 0, __count = 0, __owner = 0, __nusers = 4294967294, __kind = 0, __spins = 0, __list = {__prev = 0x0,
__next = 0x0}}, __size = ' 00' <repeats 12 times>"376, 377377377", ' 00' <repeats 23 times>, __align = 0}
现在我正在写这篇文章,__nusers和__size的值看起来很奇怪。这可能暗示锁是无效的,但我知道锁在某个时刻是有效的(我在lock类中包装了boost::互斥锁,在构造函数、析构函数和锁/解锁函数中打印了This的值(0x847840)。
任何关于如何调试这将是非常感激的帮助。
编辑Locks类继承自boost::mutex,并导出一个作用域锁(从内存):
lock_type::scoped_lock getScopedLock() {
return lock_type::scoped_lock( *this );
}
我还尝试将锁作为成员添加,而不是从它继承,而不改变行为。我不认为getScopedLock函数会引入任何问题(作用域锁返回y值,但由于RVO而没有复制),但认为它可能值得一提。它的用法如下(我们使用c++0x):
auto lock = lock_.getScopedLock();
完整的跟踪:
(gdb) where
#0 0x00007ffff559da75 in *__GI_raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007ffff55a15c0 in *__GI_abort () at abort.c:92
#2 0x00007ffff5596941 in *__GI___assert_fail (assertion=0x55851c "!pthread_mutex_destroy(&m)", file=<value optimized out>, line=47,
function=0x5595a0 "boost::mutex::~mutex()") at assert.c:81
#3 0x000000000044a2c6 in ~mutex (this=0x847840, __in_chrg=<value optimized out>) at /usr/include/boost/thread/pthread/mutex.hpp:47
#4 0x000000000044d923 in ~Lock (this=0x847840, __in_chrg=<value optimized out>) at include/Locks.h:43
#5 0x00007ffff55a3262 in __run_exit_handlers (status=0) at exit.c:78
#6 *__GI_exit (status=0) at exit.c:100
#7 0x00000000004ea9a6 in start () at src/main.cc:191
#8 0x00000000004de5aa in main (argc=1, argv=0x7fffffffe7b8) at src/main.cc:90
你通常会得到这个错误,当你unlock
你的互斥锁没有先锁定它。
boost::mutex m;
m.unlock();
我的猜测是,你在某处使用lock
和unlock
成员,而不是RAII
,并且您已经丢失了呼叫lock
的电话。
注意,大多数时候不应该调用lock
和unlock
成员。使用scoped_lock
为您调用这些函数。
struct s
{
void foo()
{
boost::mutex::scoped_lock l(m_mutex);
//do something
}
private:
boost::mutex m_mutex;
};
同样,您提到您继承了boost::mutex
。这可能会导致问题,因为boost::mutex
没有虚析构函数,所以最好不要这样做。
原来有两个问题。有一个锁,从来没有使用过,但当我停止时,我确实调用了解锁。显然,我没有正确阅读文档,因为解锁有一个先决条件,即当前线程必须拥有锁。汤姆,谢谢你让我看到这个。
第二个问题是,我在某个地方有一个作用域锁,我想在它超出作用域之前解锁它:
auto lock = lock_.getScopedLock();
if( something )
lock.unlock();
原来,这读lock_.unlock();
,所以我解锁互斥锁,而不是通过作用域锁。
@Tom,我不喜欢写boost::mutex::scoped_lock l(lock_)
的原因是,如果你写boost::mutex::scoped_lock l()
,就不会有任何错误。现在,我看到的唯一危险是有人写lock_.getScopedLock()
而没有将其存储在变量中,我想当其他人开始触摸代码时,我们只是定义一个宏来获取范围锁(是的是的,我们可以为没有getScopedLock的变体做同样的事情;))。在任何情况下,我不再继承boost::mutex
,而是保持它作为一个成员。你说得对,我们不应该冒险继承它。
@Daniel,编译-lpthread没有帮助,我没有时间看那个特定的问题,因为我不需要它,但无论如何,谢谢你的建议。
@Sam,我确实运行了valgrind,但是它没有显示出锁问题的有趣输出。
- 当回溯以零开始时,如何调试崩溃
- 在linux上调试巨大的C++项目
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 正在VS调试器中监视映射条目
- 使用调试/崩溃报告将应用程序部署到客户端
- VC++本机单元测试,找不到调试符号
- 如何在C++生成器中禁用"使用调试.dcus"
- 使用vscode调试时,GDB意外退出
- 即使使用调试编译标志,表达式也是"optimized out"
- 调试 CUDA MMU 故障
- 如何在没有死锁和/或争用的情况下正确使用 std::mutex C++?
- 小字符串优化(调试与发布模式)
- 调试和自由执行中的信号处理
- 调试编译的服务器在数据库打开时崩溃
- Visual Studio 调试优化如何工作?
- 如何配置Visual Studio Code以使用cygwin,cmake和gcc进行调试
- 从 exe 文件 (Visual Studio ) 启动时调试断言失败
- BOOST :: MUTEX版本与调试构建
- Boost::mutex, pthread_mutex_destroy失败的调试建议