2013-08-01 58 views
2

我已經將用C++和Boost編寫的長時間運行的穩定庫移植到Blackberry 10.庫在設備之間傳輸文件。該圖書館編譯和鏈接良好,並運行得很好。但是,在轉移了1,2或3個文件後,我一直在Blackberry 10設備上遇到拋出的異常。將源代碼中的異常作爲boost :: system :: system_error捕獲,顯示它爲異常16,並帶有「互斥體:資源繁忙」文本。什麼可以導致異常16:「mutex:Resource busy」被拋出(使用Boost/BB10)?

這裏就是發生異常的源代碼:

跟蹤日誌行是:

18:37:04 (149077264) [error] Boost exception (16/"mutex: Resource busy") caught in HandleQueueOperation 

的異常之間的「開始」和「結束」的評論上述某處拋出,其中定義了boost :: asio :: io_service對象。我搜索了StackOverflow,Google等與「互斥體:資源繁忙」有關的任何內容,但都沒有發現任何東西。我的代碼在這一點上沒有訪問任何應用程序級別的互斥體,所以我認爲這個互斥體是一個與Boost相關的互斥體。

有人可以告訴我消息的基本含義,以及爲什麼「資源繁忙」異常被拋出? Blackberry 10中是否存在與例外有關的已知問題?

在此先感謝!

+0

'io_service'將在各種平臺上內部使用互斥鎖來完成多項任務。但我不熟悉BB10。你可以附加一個調試器並在呼叫站點捕獲異常嗎?從'io_service'構造函數拋出異常嗎?看到堆棧跟蹤會很有用。 –

+0

到目前爲止,我還沒有成功進入Boost代碼本身,但它絕對是瞄準的方法 - 敬請期待。 –

+1

它可能是'boost/asio/detail/impl/posix_mutex.ipp',這是我能夠找到'system_error'用字符串'「mutex」'拋出的唯一地方。假設BB10是posix,如果互斥量已經被初始化,'pthread_mutex_init'可能會失敗。堆棧跟蹤將在這裏幫助。 –

回答

3

經過多次調試,一位同事終於解決了這個問題。

內容提要

例外正被調用pthread_mutex_init()後55-65 升壓::互斥構造調用拋出因爲一個應用程序級別的派生類對象,具有一個boost ::互斥作爲成員變量,因爲基類析構函數是非虛擬的,所以沒有被完全破壞。這導致boost :: mutex-s的數量上升,直到拋出互斥異常。當正確調用派生類的析構函數時,互斥異常不再被拋出。

相關/有趣的事實沿途收集

(1)早期的理論提出了有系統過多的互斥和申請超過上同步的最大數量的某種未知的限制允許的對象(儘管QNX文檔明確指出這些對象的數量是無限的)。爲了驗證這一點,我們修改了的boost ::互斥類從:

class mutex 
{ 
private: 
    . . . 
public: 
    mutex() 
    { 
     . . . 
    } 
    ~mutex() 
    { 
     . . . 
    } 
} 

到:

class mutex 
{ 
private: 
    static int _nCount; 
public: 
    mutex() 
    { 
     ++_nCount; 
     . . . 
    } 
    ~mutex() 
    { 
     . . . 
     --_nCount; 
    } 
    static int getCount() 
    { 
     return _nCount; 
    } 
    . . . 
} 

注意,使用的_nCount變量不同步(我們需要一個互斥對象這個!),但是調用應用程序中的調試boost :: mutex :: getCount()函數使我們確信,異常時的互斥量很低(平均55-65個活動互斥量)。

通過添加靜態訪問函數來監視最低級別的對象(例如Boost中的互斥體)的這種技術是調試粘性問題時需要考慮的一個好工具。(2)我們偶爾會收到一個ENOMEM異常,表明存在內存問題(「系統無法分配創建互斥鎖所需的資源」)。

(3)A FreeBSD site posting from three months ago是非常相似,我們的症狀:

我有麻煩,我似乎無法解決。我的程序 可重複創建和銷燬互斥鎖​​(顯然,它們在 之間使用它們)。在創建的第60個鎖附近,我總是獲得ENOMEM。我有 可用內存,很多。所有的鎖都會正確釋放。

不幸的是,這個線程並沒有將我們指向一個建設性的方向。 (4)當仔細研究應用程序的代碼時,發現了一個派生對象,它的基類析構函數是非虛的,從而泄漏了一些內存,這一突破來臨了。通過虛擬基類析構函數修復了內存泄漏並解決了互斥異常。

(5)即使在使基類的析構函數虛擬化之後,我們發現在使用QNX®Momentics Tool Suite編譯Blackberry 10時,並未調用派生類的析構函數。我們通過指定基本和派生的析構函數爲「虛擬」來「破解」此問題。只有這樣,派生的析構函數纔會被調用。這可能表明QNX編譯器的C++規範實現中存在錯誤,該規範明確指出虛擬傳播到派生類(Working Draft, Standard for Programming Language C++ (2012), page 250, footnote 9)。

編輯:請參閱this Stack Overflow post瞭解有關虛擬析構函數的QNX丟球的另一個示例。

相關問題