编译器优化-函数没有地址 [英] Compiler Optimizations - Function has no address

查看:919
本文介绍了编译器优化-函数没有地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

由于某些优化,编译器决定不为功能分配地址时,就会出现问题.即使在Debug,x86(禁用优化-/Od)中,VS 2015也会发生这种情况.我正在重构一个旧系统,将一些代码移到一个公共的静态库(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中移动它时,它开始崩溃!我花了大约两天的时间才终于注意到编译器在几个地方决定(但仅针对静态库)不从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 (由于这是另一个主题,因此很复杂).

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

我希望这可以对某人有所帮助.

I have not used much pointers to member functions but I think that found some dangerous scenarios when using such pointers.

The problem comes when compiler decides not to assign address to function, because of some optimization. It happened with VS 2015 even in Debug, x86 (with disabled Optimization - /Od). I am refactoring one old system, moving some code in a common static library (common.lib) so to be able to be used from several projects. Even if not the best pattern, the old implementation depends heavily from function member pointers and I do not want to change this. For example, I added the interface ModuleBase to one very big old class to something like:

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 {};
}

The idea was to move ModuleBase in the Static library, but OldModule to remain in the main EXE project. While ModuleBase was in the main project it worked fine but when I move it in the static Common.lib it start crashing! It took me about 2 days to finally notice that at several places the compiler decided (but only for the Static Library) not to assign addresses to FunctionMain, FunctionSecondary() and etc.. from ModuleBase. So when pointers to these virtual functions were passed to other routines they were zeroes.

For example in the code bellow:

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

The last member in the structure was zero but only when is in the static library. It was quite nasty because I had to check many other things before to notice this. Also there are other pointers which were not zero because the structure was not zeroed in the constructor so one has to notice that address value is different and crashes when trying to call the function.

So my questions are - 1) Am I seeing this right - is this valid situation (that compiler is removing functions addresses, for the same code when moved in a static library)?

2) How to force compiler always to keep the member function addresses?

解决方案

My apology, I found no problems with the addresses of pointers-to-members-functions in Visual Studio. Pointers to the base interface virtual functions are resolved Ok, even if placed in a Static Library. Reasons for my problems were:

1) Debugger sometimes shows function addresses of template classes as zeroes

2) Reason for the crashes was that the main project had the /vmg compiler option, but I missed to put it in the Static Library project. In such case one should be careful to use /vmg always in all referenced library projects (complications because of it is another topic).

Anyway, using pointers-to-members functions together with the object pointer is usually a sign of bad underlying design.

I hope this may help someone.

这篇关于编译器优化-函数没有地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆