![](/img/trans.png)
[英]error C2039 : 'WaitForSingleObject' is not a member of 'boost::detail::win32'
[英]Boost.Thread Assertion/Crash on Windows during win32::WaitForSingleObject
我的代碼中有一個很少發生的問題,其中觸發了一個斷言,涉及 Boost.Thread 庫。 我一直無法使用獨立示例重現此問題,並且我真的不知道是什么原因導致的,因此很難提供示例案例。 我希望任何熟悉 boost.thread 內部結構的人都可以提供幫助。
這是我所知道的:
boost::lock_guard<boost::recursive_mutex>
(或 unique_lock 和普通非遞歸互斥鎖的變體)時,就會出現問題。io_service::run
的線程,一堆膠水來調用 Asio 回調函數,然后是我的回調函數(由 async_write 調用觸發)。 該函數的第一行是導致問題的lock_guard<>
的聲明。this
是有效的,並且沒有被刪除或類似的東西。 調試器顯示它指向有效數據。 在我的handle_write
函數中鎖定的互斥鎖還可以防止刪除處理函數使用的內存。lock()
互斥的方法(在的構造函數boost::unique_lock<>
然后調用lock()
中boost::detail::basic_recursive_mutex_impl
,它調用lock()
的方法boost::detail::basic_timed_mutex
。 在 Boost 1.46 中,斷言 ( 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
代碼路徑所做的),沒有其他線程持有互斥鎖(至少在斷言發生時,可以在調試器)。 這很奇怪,因為它應該能夠獲得鎖而不必等待另一個線程放棄控制權。sem
- 0xdddddddddddddddd - 在每次崩潰時總是相同的。lock_acquired
-假。old_count
- 0xdddddddddddddddd 。this
- 似乎是有效的,並且它的地址與持有它的對象( handle_write
是一個方法的對象)相匹配。 它似乎沒有以任何方式被刪除或弄亂。this->active_count
- 一個負整數,我見過的范圍在 -570000000 和 -580000000 之間。this->event
- 0xdddddddddddddddd 。 不幸的是,我無法看到WaitForSingleObject
調用的結果。 API 函數上的MSDN 條目指示四種可能的返回類型,其中兩種在這種情況下是不可能的。 由於WaitForSingleObject
使用無效的事件句柄 ( sem
= 0xdddddddddddddddd
) 被調用,我假設它返回0xFFFFFFFF
並且 GetLastError 將表明提供了一個無效的句柄。
所以實際的問題,現在看來,是該get_event()
的方法basic_timed_mutex
將返回0xdddddddddddddddd
。 但是, CreateEvent
的MSDN 條目( get_event()
最終使用)告訴我它返回事件的有效句柄或NULL
。
同樣,這可能是我可以提供的問題的最佳描述,因為它在此特定應用程序之外無法可靠地重現。 我希望有人對可能導致這種情況的原因有想法!
我想很難對您的問題給出准確的答案,但是您似乎遇到了堆損壞問題,您是否嘗試過在啟用了正常頁堆的情況下使用 AppVerifier? 如果您隨后將調試器附加到進程並發生堆損壞,則它有望在遇到損壞的堆塊時中斷,您甚至可以查看分配代碼的調用堆棧。
編輯:如果使用 WinDbg,您還可以在 WaitForSingleObject(或任何其他函數)上放置一個條件斷點,僅當調用失敗時才中斷,然后檢查最后一個錯誤,例如: bp kernel32!WaitForSingleObject "gu; .if(eax == 0) {g}" -> 這將告訴調試器在斷點處 i) 運行到函數的末尾 (gu) 和 ii) 檢查返回值(存儲在 EAX 寄存器中)並繼續執行 (g) 如果一切正常美好的。 如果返回錯誤,您可以使用!gle擴展命令檢查 GetLastError() 的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.