我試圖將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 本身未初始化。
有沒有法律說,一個破壞內部結構的C++錯誤必須涉及「調用crt或一些不明確的庫」。你的代碼中有一個bug。除了「找到你的bug並修復它」之外,沒有別的回答你的問題。 –
@SamVarshavchik那麼,當它被編譯成非託管的DLL偉大的,但是這個代碼工作。你能告訴我_如何用零填充所有vtable表?我不知道在哪裏看。 – Amomum
嘛,也不是有,說只有一種可能的方式來破壞內存的法律。任何地方都可以寫入未初始化的或懸掛的指針,任何地方都有「未定義的行爲」。這就是「未定義行爲」的含義。你的錯誤可以在你的代碼中的任何地方,沒有任何法律要求某種特定的錯誤總是以某種特定的方式發生。 –