对于成员函数,我没有使用太多的指针,但我认为在使用这些指针时发现了一些危险的情况。
由于一些优化,当编译器决定不为函数分配地址时,就会出现问题。它发生在VS 2015,甚至在调试,x86 (与禁用优化- /Od)。我正在重构一个旧系统,在一个公共静态库(common.lib)中移动一些代码,以便能够从多个项目中使用。即使不是最好的模式,旧的实现在很大程度上依赖于函数成员指针,我不想改变这一点。例如,我将接口ModuleBase添加到一个非常大的老类中,例如:
class ModuleBase
{
public:
typedef void (ModuleBase::*Main)() const; // moved from old module
virtual void FunctionMain() const = 0; // Function has no address, possibly due to compiler optimizations.
virtual void FunctionSecondary() const = 0; // Function has no address, possibly due to compiler optimizations.
};
class OldModule : public ModuleBase
{
public:
virtual void FunctionMain() const {};
virtual void FunctionSecondary() const {};
}
这样做的目的是在静态库中移动ModuleBase,但将OldModule保留在主EXE项目中。当ModuleBase在主项目中时,它工作得很好,但是当我在静态Common.lib中移动它时,它就开始崩溃了!我花了大约两天的时间终于注意到,在几个地方,编译器决定(但只为静态库)不为FunctionMain、FunctionSecondary()等分配地址。来自ModuleBase。因此,当指向这些虚拟函数的指针被传递到其他例程时,它们是零。
例如,在下面代码中:
new Manager::ModuleDecription(
"Test Module",
"Secondary Scene",
"Description"
PosX,
PosY,
Proc,
&ModuleBase::FunctionSecondary //contains nullptr when in static library!!!!!
结构中的最后一个成员为零,但只有在静态库中时才是。这是相当令人讨厌的,因为我必须检查许多其他事情之前,注意到这一点。此外,还有其他指针不是零,因为结构没有在构造函数中归零,因此必须注意到,在尝试调用函数时,地址值是不同的,并且会崩溃。
因此,我的问题是- 1)我是否看到了这个正确的-这是有效的情况(编译器正在删除函数地址,为相同的代码时,在静态库中移动)?
2)如何强制编译器始终保持成员函数地址?
发布于 2019-01-31 00:13:00
对不起,我发现在Visual中指向成员的指针的地址没有问题。指向基本接口虚拟函数的指针被解析为Ok,即使放在静态库中也是如此。我出现问题的原因是:
1)调试器有时将模板类的函数地址显示为零
2)造成崩溃的原因是主项目有/vmg编译器选项,但我没有将其放在静态库项目中。在这种情况下,应该小心地在所有引用的库项目中使用/vmg (因为这是另一个主题)。
无论如何,使用指针到成员函数和对象指针通常是糟糕的底层设计的标志。
我希望这能帮上忙。
https://stackoverflow.com/questions/54388905
复制相似问题