2010-06-15 33 views
1

這是我的問題。我正在製作C++ dll,它廣泛依賴於實例對象導出。 因此,我通過一些導出的工廠方法將我的實際實例作爲指向接口的指針返回。界面中的純虛擬析構器

我使用的接口純粹是虛擬的,以避免鏈接problame。所以我也需要一個純粹的虛擬析構函數,並且我實現了一個(空的主體,因爲我使用了它)。 所有編譯完好,除了...我看不到,如果實際的析構函數被調用或不 - 因爲當我添加一些

std::cout << "hello destructor";
我永遠不會看到它。我有一些顯式的「刪除OBJ」(編輯:它是從DLL中的「FreeObject」方法調用),這不是問題。

我錯過了什麼?有另一種通過界面刪除我的對象的方法嗎?

編輯:再次,我沒有內存管理不一致,這一切都在DLL內。但是,正確的析構函數就不會啓動。

回答

4

您不應該在DLL邊界上混合匹配newdelete的調用。

相反,我會推薦COM使用的嘗試和真實的方法:AddRefRelease。當引用計數達到零時,Release從DLL內部調用delete this;,確保newdelete匹配。

+0

已經關心了這一點。 我編輯了我的問題清楚。 – ALOR 2010-06-15 03:38:15

+1

我仍然建議使用COM AddRef/Release模式。 'FreeObject'聽起來像一個非常通用的名字,參數是如何定義的?刪除的指針必須至少具有編譯時類型,至少與聲明虛擬析構函數以便虛擬刪除發生的基類相同 - delete(void *)p將永遠不會調用p上的任何析構函數。 – 2010-06-15 03:42:33

+1

10年前,當運行時只能作爲靜態庫使用時,使用新的/刪除跨dll bun烘乾是一個問題。這個問題是通過引入運行時DLL的共享lib版本解決的(這意味着整個應用程序只有一個堆)。除非你「手動」加載/卸載dll的使用新的/刪除跨DLL乾燥不再是一個問題。 – 2010-06-15 06:57:38

0

根本不需要析構函數。正確的析構函數只能由delete調用者看到。在DLL之外,使用接口指針作爲句柄,而不是你可以創建/銷燬的東西。對象構造/銷燬應該在DLL內部。您可以使用引用計數或任何其他您想要的技術,只需提供適當的導出來訪問和操作對象,即可決定封裝多少內存管理。

1

這是我如何解決您的具體問題進行動態加載的C++類 -

有可插拔對象的基類,即

class object_t { 

public: 
    virtual ~object_t(); 

//other type utils... 

}; 

對所有插件接口的基本接口,即

class object_t; 

class interface_t { 

public: 
    virtual object_t* object() = 0; 

} 

object_t將有鏈接,將其定義在它自己的dll中,您將鏈接到插件類。在object_t中有其他有用的鉤子是複製,產卵,RTTI和其他類型的utils,我的基礎對象例如有spawn(),copy(),object_name()。

所以所有的具體類都從object_t和它們各自的純虛擬接口類型派生,並且所有發佈的(可插入的)接口都從interface_t派生。

然後,你可以加載插件,使用工廠實例化接口,並刪除正是如此 -

delete interface->object() 

而作爲object_t有一個虛析構函數正確的析構函數會被調用。

Theres在linux下刪除對象的地方沒有問題,如果所有插件/可執行文件都鏈接到相同的動態(dll)CRT,那麼它在窗口下就沒有問題。

+0

這個術語「dll」意味着Windows,在Linux上他會說「如此」(共享對象)。此外,所有的二進制文件與相同的CRT鏈接是非常困難的要求想象一下,如果你想編寫一個資源管理器上下文菜單插件,並且微軟表示「爲了與舊插件的向後兼容性,我們仍然使用Visual C++ 4.0進行編譯,你也必須這樣做,所以忘記使用異常,模板或您插件中的任何其他現代C++功能「。 – 2010-06-15 13:44:29