2009-12-08 78 views
7

好了,所以這是一個很長升技解釋跟我這麼裸..C++:加載一個EXE的DLL,本地vftable問題

我有一個名爲exe文件test.exe的這通常是作爲一個獨立單獨應用。我想在另一個應用程序app.exe中使用這個exe作爲一個模塊(一個dll)。

在test.exe的代碼確實非常簡單喜歡的東西:

void doTest() 
{ 
    MyClass *inst = new MyClass(); 
    inst->someMethod(); 
} 

哪裏someMethod()是虛擬和MyClass的具有虛擬D'TOR。
doTest()從test.exe導出,因此創建一個名爲test.lib的庫
app.exe與此lib鏈接,以在啓動時靜態加載test.exe。

當我運行test.exe的單機運行得很好,但,當我運行它從內APP.EXE崩潰加載。
使用調試器進入代碼顯示崩潰在調用虛擬方法。事實證明,vFtable不知何故變壞了。

經過一番調查發現,當MyClass的構造函數內部的代碼正在運行時,vftable是一回事,但當new的調用返回時,它將替換爲其他稱爲「本地vftable」的東西。我發現this obscure discussion about why this is

後大約一天的時間調試它發生,我認爲在這個「本地vftable」的指針是在兩種情況下是相同的,當test.exe的是獨立自主,它則作爲一個模塊加載的。這是不對的,因爲test.exe被加載到不同的地址...
爲了測試這個理論,我將鏈接器選項中的加載地址更改爲test.exe在app.exe中加載時的加載地址現在,瞧,一切都有效。

顯然,這是不是因爲下一次該隨機選擇的地址可能被佔用,將再次出現同樣的問題長久之計。

所以我的問題:爲什麼這種「本地vftable」捆綁exe文件的靜態加載地址?加載一個exe作爲一個模塊是一件壞事?爲什麼exe假定它被加載到它的靜態地址?

只爲背景:這是所有與2008年MSVC完成,Windows XP的64位。

回答

3

我最終使用的解決方法是簡單地添加一個編譯配置,並將exe編譯爲真正的dll,而不是強制它像一個行爲。

使用/fixed:no沒有解決出於某種原因的問題。

exes和DLL之間的另一個區別是入口點不同。 DLL的入口點是DllMain,其中exe作爲入口點在CRT中,最終調用main()或WinMain()。