2015-02-24 62 views
-1

我試圖找出這個問題。使用boost :: signals2和卸載DLL時訪問衝突

假設您的代碼使用boost::signals2進行對象之間的通信。讓我們稱他們爲「色彩」。這些colorscales的代碼通常位於與使用它們的代碼相同的DLL中。我們稱之爲main.dll

但是有時來自其他DLL的代碼需要使用這些對象,這就是問題開始的地方。

基本上,應用程序是相當大的,大多數的DLL被加載做一些工作,然後他們被卸載。對於包含colorscales代碼的DLL,情況並非如此,它在應用程序正常運行時期間被卸載。因此,當其中一個DLL被加載(我們稱之爲tools.dll)並且一些代碼運行時,它可能想要使用這些色彩對象並與它們通信,因此我連接到這些對象提供的信號。

的問題是,boost是非常懶惰,所有的聰明,當你disconnect()插槽,它實際上並沒有抹去connection和與它(如boost::bind對象,例如)相關的東西。它只是設置一個標誌,這個connection現在已斷開連接,並在稍後清理它(實際上,當您連接新插槽時清除其中的2個對象,當您調用1.57版本時調用其中的1個對象)。你可能已經看到了這將會到來。

所以,當你不需要更多的工具時,你斷開這些信號,然後卸載應用程序tools.dll

然後在稍後的階段,一些代碼從main.dll執行,導致一個色彩信號被調用。 boost::signals2去調用它,但在它試圖清理一個斷開的插槽之前。這是發生訪問違規的地方,因爲內部連接有一個shared_state對象或類似的東西,它試圖以線程安全的方式清理自己。但它面臨的問題是,它試圖調用的代碼已經不存在,因爲DLL被卸載,所以引發了Access Violation異常。

我試圖通過在卸載DLL之前調用帶有一些虛擬參數的信號來解決這個問題,並且通過連接然後斷開更多的插槽來解決這個問題(這是一個愚蠢的想法,因爲它不能解決問題,它)一些預定義的時間量(比所有時隙多2或3倍)。

它的工作,或我認爲是這樣,因爲它現在不會立即崩潰,而是在下次加載相同的tools.dll時崩潰。我仍然需要弄清楚它在哪裏以及爲什麼會崩潰,但它在boost之內的其他地方。

所以,我想問一下,我有哪些修復方法? 我的想法是

  • 實現我自己的連接,在一個更簡單的方式
  • 提供了一個更簡單的方法來溝通一樣,回調的作品,例如
  • 找到一個解決方法boost如此懶惰和聰明。
+0

你有沒有想過不通過DLL傳遞提升對象?重新發明whell(子彈一)是一個壞主意。找到解決方法將幫助您瞭解更多信息,但可能需要無限期的時間。我會去更簡單的方法。 – UmNyobe 2015-02-24 18:57:14

+0

那麼,這是問題的全部。這是因爲它沒有解決方法就無法工作。問題是:我應該選擇哪種解決方法 – Spo1ler 2015-02-24 23:10:11

回答

0

嗯,似乎我已經找到修復後崩潰的原因。

所以,基本上,會發生什麼,當你使用上面(與虛擬參數多次呼叫信號)中描述的解決方法,它的作用是,它取代了從boost代碼由另一個_shared_state對象創建從main.dll_shared_state對象創建自的代碼boost。該對象維護指向參考計數器(類型派生自boost::detail::sp_counter_base)的指針。

然後tools.dll卸載並保留對象,但其虛擬表指向不再存在的代碼。讓我們看看參考計數器的虛擬表格,瞭解發生了什麼。

[0] 0x000007fed8a42fe5 tools.dll!boost::detail::sp_counted_impl_p<...>::`vector deleting destructor'(unsigned int) 
    [1] 0x000007fed8a4181b tools.dll!boost::detail::sp_counted_impl_p<...>::dispose(void) 
    [2] 0x000007fed8a4458e tools.dll!boost::detail::sp_counted_base::destroy(void) 
    [3] 0x000007fed8a43c42 SegyTools.dll!boost::detail::sp_counted_impl_p<...>::get_deleter(class type_info const &) 
    [4] 0x000007fed8a42da6 tools.dll!boost::detail::sp_counted_impl_p<...>::get_untyped_deleter(void) 

正如你所看到的,所有這些方法都連接到處理引用計數的,所以你嘗試做同樣的伎倆第二次之前不會出現這個問題。所以,斷開所有信號以試圖擺脫tools.dll中的所有代碼的技巧並不像預期的那樣工作,並且下次嘗試執行該技巧時,會發生Access Violation

+0

很大,你正在取得進展。你有沒有找到你的解決方法? – UmNyobe 2015-02-25 12:50:56

+0

我認爲,如果我將這種「詭計」的代碼移動到擦除斷開的插槽到'main.dll',它將實際上工作,由於上述原因。 – Spo1ler 2015-02-25 13:05:42

+0

或者我可以只使用其他語言工具進行通信(就像在項目中使用的Qt一樣),因爲'main.dll'之外的代碼不需要全部的信號信息。 – Spo1ler 2015-02-25 13:07:28