2017-08-23 120 views
0

我試圖將C++代碼編譯爲託管dll。我可以用這個編譯器和連接選項編譯:填充零的Vtable

編譯:

/TP /analyze- /W3 /Zc:wchar_t /Zi /Od /sdl- /Fd"Debug\vc140.pdb" /Zc:inline /fp:precise /D "_SCL_SECURE_NO_WARNINGS" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Oy- /clr:pure /FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll" /MDd /Fa"Debug\" /nologo /Zl /Fo"Debug\" /Fp"Debug\aaa.pch" 

鏈接:

/OUT:"C:\Out\x86\Debug\aaa.dll" /MANIFEST /NXCOMPAT /PDB:"C:\aaa.pdb" /DYNAMICBASE "ucrtd.lib" "vcruntimed.lib" "libvcruntimed.lib" "msvcurtd.lib" "msvcrtd.lib" "libcmtd.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /FIXED:NO /DEBUG /DLL /CLRIMAGETYPE:PURE /INCREMENTAL:NO /PGD:"C:\Out\x86\Debug\aaa.pgd" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\aaa.dll.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /ASSEMBLYDEBUG /TLBID:1 

我的問題是,真的很奇怪。我有一個純粹的抽象基類和該dll中的派生類。當我用new創建派生類的一個實例時,我可以看到它的虛表充滿了零。

所以我不能調用任何虛函數。

我無法用虛擬控制檯應用程序重新創建此問題,所以我不知道,這可能是什麼原因。就我從虛擬應用程序中看到的情況來看,沒有調用crt或一些不太明確的庫來用正確的地址填充vtable,只有幾條裝配線。

UPDATE:

在代碼的問題是這樣的:

class Connector : public IConnector 
{ 
    public: 
     Connector() : m_a(0), m_b(0) 
     {} 
    <...> 
}; 

<...> 

Connector * pc = new Connector(); 
Connector c; 

IConnector具有默認的構造函數,並沒有字段,所以它什麼都不做。

在監視窗口中,我可以看到pc和c中的vtable指針設置爲非零值,它們是相同的。但他們指出的地方充滿了零。

恕我直言,它看起來不像vtable指針被破壞,它看起來像vtable 本身未初始化。

+0

有沒有法律說,一個破壞內部結構的C++錯誤必須涉及「調用crt或一些不明確的庫」。你的代碼中有一個bug。除了「找到你的bug並修復它」之外,沒有別的回答你的問題。 –

+0

@SamVarshavchik那麼,當它被編譯成非託管的DLL偉大的,但是這個代碼工作。你能告訴我_如何用零填充所有vtable表?我不知道在哪裏看。 – Amomum

+0

嘛,也不是有,說只有一種可能的方式來破壞內存的法律。任何地方都可以寫入未初始化的或懸掛的指針,任何地方都有「未定義的行爲」。這就是「未定義行爲」的含義。你的錯誤可以在你的代碼中的任何地方,沒有任何法律要求某種特定的錯誤總是以某種特定的方式發生。 –

回答

0

好的,我發現了這個問題。要創建純管理的dll我用這個答案Creating a pure MSIL assembly from a C++/CLI project?

第6步建議加入這個片段:

#pragma warning(disable:4483) 
void __clrcall __identifier(".cctor")() { } 

我不是很好用C#,所以我只是把它抄了沒有任何瞭解。這讓在這一點上消除一些錯誤的,所以當一切建造我剛離開那裏,並忽略警告,這樣的(因爲我不能google一下他們什麼):

Warning LNK4210 .CRTMA section exists; there may be unhandled static initializers or terminators 

(我知道我應該提到它的問題,但它太容易忽視有關的警告給忘了。無視警告是不好的,m'kay?)

Apparanetly這個東西叫做「模塊contstructor」,它確實喜歡初始化全局和靜態變量很多重要的事情和,對於那個特別的問題,vtables。

看起來這個答案的作者並沒有使用任何那麼空的ctor爲他工作。

我剛剛刪除了這個空模塊ctor和vtables現在不是空的。