2016-06-21 29 views
2

有幾個關於從構造函數中拋出並拋出DLL邊界的問題,但是我找不到能夠解決這個特定情況的問題。通過DLL邊界從構造函數中引發異常

兩件事情我已經知道:

  1. 構造方法應拋出異常,如果有什麼不好的事情發生。這確保了對象不會處於殭屍狀態,不需要函數來檢查對象的狀態,並執行RAII。一切美好的事物。

  2. 我們不應該拋出DLL邊界。堆內存不共享,並且可能發生不好的事情。這個細節讓我有些失望,但是到處都是一般的建議不是這樣做的,所以我不會這麼做。這裏的異常(!)是所有代碼都是用同一個編譯器編譯的,但即使這似乎是編譯器特有的,也是不可靠的。錯誤代碼是!

現在我的問題:

如何安全地創建這是在一個DLL某處定義的類的實例?

我認爲也許唯一安全的方法是使DLL中的所有(Exported)構造函數保證不會拋出異常,或者提供導出的自由函數,它返回指向可能爲NULL的對象的指針如果發現異常。

任何人都可以提出更適合的任何東西,或者告訴我我的棒有錯了嗎?

+0

您需要確保exe和dll都使用相同版本的運行時支持,並且它是dll版本而非靜態版本。 –

+2

值得你花時間閱讀:[如何在DLL中使用類?](http://stackoverflow.com/questions/4555961/how-to-use-a-class-in-dll)。解答幾乎所有的問題和一些你還沒有想到的。 – user4581301

+0

我甚至不喜歡導出一個類,因爲DLL的錯誤版本可能會導致問題。但是,如果該類在內部用於實現導出的函數,那沒關係。上面的註釋鏈接通過僅導出接口避免了這種情況。 –

回答

1

我認爲你的方法是正確的。讓我們將工廠導出爲對象而不是對象本身。

順便說一句,它可以被預測,以便您的每個DLL可以有一個具有相同名稱的導出功能。因此,在該導出函數中,您可以通過if-else塊來枚舉DLL的所有工廠並嘗試構建請求的對象。 (比方說,對象是通過名稱,名稱crc32,名稱散列等來標識的)

我認爲這可能是幾種方法。 例如,可以在DLLMain/Attach事件上的公共對象上註冊DLL的每個工廠,或者處理自定義的DLLMain事件 - 您自己的 - 以便您可以將Neo對象地址作爲參數DLLMain併爲其註冊每個DLL的確切工廠。

但常見的是當你的對象可能對ctor/init方法拋出異常時使用工廠。

+2

我已經完成了提供工廠函數來創建類對象的dll,但只提供了指針作爲句柄。類本身不導出,只能通過導出的函數使用。 –