不正确的虚表的布局类出口的DLL:请求澄清关于标题和虚表的建筑
题
尽管手头的问题是 解决了, 它让我有点困惑为什么数据被用于建造vtable都从一类和布局的虚表被存储。如果任何人都可以提供澄清或者指出我对一些信息可能会满足我的好奇心,我将不胜感激。
背景
- 两个单独的VC6.0项目:一个可执行软件,一个用于dll。
- 应用程序包含的内容。lib.dll。h文件从dll项目的版本。
- 当一个新的版本是准备。lib.dll。h文件 复制 到exe项目从dll项目。
- 我继承了这种方案。
问题:
我最近做了一个改变DLL和复制。lib和。dll但是 忘了复制文件标题.已经有一些层次结构的变化,因此,虚表的一个特别类(称呼它 InternalClass
)发生了变化。
Exe不会 没有直接援引任何方法上的 InternalClass
.相反,它创建的一个实例,一个不同的类(称呼它 InterfaceClass
)其封装了一个指向一个 InternalClass
对象和调用各种方法对这一指针。
在运行时,呼吁从内 InterfaceClass
方法 InternalClass
方法进行实际调用 错误的方法 (即 InterfaceClass
将调用 InternalClass::A
和 InternalClass::B
实际上会运行)。看 asm, ,原来的修正或想到(我很抱歉如果这是错误的行话!) 使用正确的 抵消 到虚表. 然而, ,虚表本身所载的清单为指针,你会期望从 旧 头文件。
实际问题:
我意识到我的错误、抄袭的头文件,重新编译和切都很好。 然而, 我留下一个唠叨的问题:
当布局vtable都从确定和什么样的信息是用来建造的虚表对于这些课程在运行时?这就是,在我看来这的 正确的 虚表必须已经装配好时dll was compiled使偏移等可能是使用的电话从 InterfaceClass
要 InternalClass
.那么,为什么是过时的虚表用于在运行时?是的布局 还 分别确定当exe编制使用的标题已?
我不知道如果这是在所有清楚的。 如果让我知道我在问什么是太令人费解的。谢谢!
解决方案
嗯,沉重的责任执行情况的详细信息的一个12岁的编译器。当你使用的声明影响(dllexport)上级,连接出口成员的类。不虚表.得到重建在客户的类时,编译器分析这类声明中的标题的文件。连接填补当地的虚表的出口成员的地址。
它会更好地工作,如果编译器只出口的虚表从DLL?也许,但是出口,这种实现的细节是非常脆弱。恐惧的画自己到一个角落里,你不能出去的因为向后兼容性是一个强大的动力,我想象的。
其他提示
你描述的相互作用的这两个类别并不完全清楚在一个非常重要的细节:是你所谓的 InternalClass
出口从dll或没有?或者把这个问题的不同方式:没有代码在那些头的复制文件中使用的指针 InternalClass
或是 所有 知识的这一类仅仅隐藏在dll?
如果这类问题实际上是完全的隐藏内的问题,然后我不知道该如何这个问题可能发生。但是,从你所描述的,它真的声音,因为如果 InternalClass
正在暴露出来的dll。
如果这些头,得到复制包含码在概念上类似于这样的:
class InterfaceClass
{
InternalClass* Internal;
void DoSomething()
{
Internal->DoSomething();
}
};
那么 InternalClass
必须将暴露出来,否则[执行的项目将无法编制的标题。(所以它不是真正内部之后。)
如果是这种情况,那么它很容易解释你的问题。Exe正在建设针对不同宣言 InternalClass
比dll建。这意味着每个编译自己版本的虚拟表,而这些版本是不同的。
然后在运行时,[执行码是手创建的对象从内的问题,并因此与其虚表指针指向dll的版本,虚表.Exe代码然后试图通过这一虚表指针,如果它指出可执行软件的版本,虚表.显然,引起的问题。