在我的代码中有一个很less发生的问题,其中一个断言被触发,涉及到Boost.Thread库。 我不能用一个独立的例子来重现这个问题,我也不知道是什么原因造成的,所以很难提供一个样例。 我希望任何熟悉boost.thread的内部人员都可以提供帮助。
这是我所知道的:
boost::lock_guard<boost::recursive_mutex>
(或者unique_lock和普通非recursion互斥体的变体)被声明时,就会出现这个问题。 io_service::run
,一堆胶水来调用Asiocallback函数,其次是我的callback函数(由async_write调用触发)。 该函数的第一行是导致问题的lock_guard<>
的声明。 this
里面的我的function是有效的,并没有被删除或类似的东西。 debugging器显示它指向有效的数据。 被locking在我的handle_write
函数中的互斥handle_write
还可以防止删除处理函数使用的内存。 lock()
方法(在boost::unique_lock<>
的ctor中),然后在boost::detail::basic_recursive_mutex_impl
中调用lock()
,它调用lock()
方法boost::detail::basic_timed_mutex
。 在Boost 1.46中,assertion( BOOST_VERIFY
)位于basic_timed_mutex.hpp的第78行,它调用了win32 :: WaitForSingleObject:
do { BOOST_VERIFY(win32::WaitForSingleObject( sem,::boost::detail::win32::infinite)==0); clear_waiting_and_try_lock(old_count); lock_acquired=!(old_count&lock_flag_value); } while(!lock_acquired);
WaitForSingleObject
代码path)的锁时,没有其他线程持有互斥锁(至less在断言发生的时候,并且可以在debugging器)。 这很奇怪,因为它应该能够获得锁而不必等待另一个线程放弃控制权。 sem
– 0xdddddddddddddddd – 在每次崩溃时总是相同的。 lock_acquired
– false 。 old_count
– 0xdddddddddddddddd 。 this
– 看起来是有效的,它的地址匹配持有它的对象( handle_write
是一个方法的对象)。 它似乎没有以任何方式被删除或混淆。 this->active_count
– 一个负整数,我见过的范围一直在-570000000和-580000000之间。 this->event
– 0xdddddddddddddddd 。 我很遗憾不能看到WaitForSingleObject
调用的结果。 API函数中的MSDN条目指示了四种可能的返回types,其中两种在这种情况下是不可能的。 由于WaitForSingleObject
被一个无效的事件句柄( sem
= 0xdddddddddddddddd
) 0xdddddddddddddddd
,我认为它返回0xFFFFFFFF
和GetLastError将表明一个无效的句柄已经提供。
所以实际的问题似乎是, get_event()
方法返回0xdddddddddddddddd
。 但是, CreateEvent
的MSDN条目 ( get_event()
最终使用)告诉我,它返回一个有效的事件句柄或NULL
。
再次,这可能是我可以提供的问题的最好的描述,因为在这个特定的应用之外它不可靠地重现。 我希望有人有什么可能导致这个问题的想法!
我想这将是非常困难的给你一个精确的答案你的问题,但似乎你有一个堆腐败问题,你有没有试图使用正常pageheap启用AppVerifier? 如果您随后将调试程序附加到进程中,并且发生堆损坏,那么当遇到损坏的堆块时,它可能会中断,甚至可以查看分配代码的调用堆栈。
编辑:如果使用WinDbg,你也可以在WaitForSingleObject(或任何其他函数)上打破条件断点,只有在调用失败的情况下,才能检查最后的错误,例如: bp kernel32!WaitForSingleObject“gu; .if(eax == 0) {g}“ – >这将告诉调试器在断点i)运行到函数(gu)的末尾,ii)检查返回值(存储在EAX寄存器中)并继续执行(g)精细。 如果返回错误,您可以使用!gle extension命令检查GetLastError()的值。