我试图将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
嘛,也不是有,说只有一种可能的方式来破坏内存的法律。任何地方都可以写入未初始化的或悬挂的指针,任何地方都有“未定义的行为”。这就是“未定义行为”的含义。你的错误可以在你的代码中的任何地方,没有任何法律要求某种特定的错误总是以某种特定的方式发生。 –