编译器优化 - 函数没有地址

2024-06-28

我没有使用太多指向成员函数的指针,但我认为在使用此类指针时发现了一些危险的情况。

当编译器由于某些优化而决定不为函数分配地址时,就会出现问题。 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 中时,它开始崩溃!我花了大约 2 天的时间才终于注意到,在几个地方,编译器决定(但仅限于静态库)不将地址分配给 ModuleBase 中的 FunctionMain、FunctionSecondary() 等。因此,当指向这些虚拟函数的指针传递给其他例程时,它们为零。

例如在下面的代码中:

new Manager::ModuleDecription(
        "Test Module",
        "Secondary Scene",
        "Description"
         PosX,
         PosY,
         Proc,
         &ModuleBase::FunctionSecondary   //contains nullptr when in static library!!!!!

结构中的最后一个成员为零,但仅当位于静态库中时才如此。这非常令人讨厌,因为我必须先检查很多其他事情才能注意到这一点。还有其他不为零的指针,因为该结构在构造函数中未归零,因此必须注意地址值不同,并且在尝试调用该函数时会崩溃。

所以我的问题是 - 1)我是否认为这是正确的 - 这是有效的情况(编译器正在删除函数地址,对于在静态库中移动时的相同代码)?

2)如何强制编译器始终保留成员函数地址?


抱歉,我发现 Visual Studio 中成员函数指针的地址没有问题。指向基接口虚函数的指针已解析好,即使放置在静态库中也是如此。我的问题的原因是:

1) 调试器有时将模板类的函数地址显示为零

2)崩溃的原因是主项目有/vmg编译器选项,但我错过了将其放入静态库项目中。在这种情况下,应该小心使用/vmg始终在所有引用的库项目中(因为它而导致的复杂性是另一个主题)。

无论如何,将成员函数指针与对象指针一起使用通常是底层设计不良的标志。

我希望这可以帮助某人。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

编译器优化 - 函数没有地址 的相关文章

随机推荐