最近我们在遗留代码中遇到了目前从VS2010移植到VS2015的有趣效果。不幸的是,我无法创建一个显示这种效果的小例子,但我会尝试尽可能准确地描述它。
我们有2个dll(我称之为dll A和dll B)。 dll A的项目定义了接口IFoo&派生接口IFxFoo
class __declspec(novtable) IFoo {
public:
virtual int GetType() = 0;
virtual ~IFoo() {}
};
class __declspec(novtable) IFxFoo : public IFoo {
public:
virtual int GetSlot() = 0;
};
在dll B中,使用了两个接口。
class CBImpl : public IFxFoo {
public:
...
void processFoo(IFoo* f) {
...
if (f->GetType() == IFXFOO) {
IFxFoo* fx = static_cast<IFxFoo>(f); //downcast
fill(fx);
}
}
void fill(IFxFoo* fx) {
m_slot = fx->GetSlot();
}
private:
int m_slot;
};
将使用不同的IFoo实现调用processFoo()。一些来自dll A,一些来自dll B.
现在发生的事情如下: - 如果我们在编译dll B时打开整个程序优化,则函数fill()中对虚函数GetSlot()的调用被Visual C ++去虚拟化。这导致我们的程序崩溃。 如果我们要么
,我们可以解决这个问题我现在的问题是:
感谢您的帮助 托拜厄斯
答案 0 :(得分:0)
使用LTO会导致编译器对任何能够查看完整调用图的函数进行大幅调整。
您所看到的是预期并使用__declspec(dllexport)
或extern
对需要从单独模块使用的函数或明确声明它们作为DLL .def文件的一部分是预期的方式解决问题,因为编译器将不再将函数视为仅内部函数。