2017-08-23 121 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现在不是空的。