Оптимизация компилятора - функция не имеет адреса - PullRequest
0 голосов
/ 27 января 2019

Я разработчик C ++ с некоторого времени, но я не использовал много указателей на функции-члены.Я нашел уже несколько опасных сценариев при использовании таких указателей.Мне нужен коллега с большим опытом, чтобы объяснить это дальше, потому что отладка и анализ не так просты.

Проблема возникает, когда компилятор решает не назначать адрес функции из-за некоторой оптимизации.Со мной это случилось с VS 2015 даже в Debug, 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 дней, чтобы наконец заметить, что в нескольких местах компилятор решил (но только для статической библиотеки) не назначать адреса FunctionMain, FunctionSecondary () и т. Д. Из ModuleBase.Поэтому, когда указатели на эти виртуальные функции были переданы другим подпрограммам, они были нулями.

Например, в приведенном ниже коде:

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

Последний член в структуре был нулевым, но только в статической библиотеке.Это было довольно неприятно, потому что мне пришлось проверить много других вещей, прежде чем это заметить.Также есть другие указатели, которые не были нулевыми, потому что структура не была обнулена в конструкторе, поэтому нужно заметить, что значение адреса отличается и вылетает при попытке вызвать функцию.

Итак, мои вопросы - 1)Правильно ли я вижу это - это допустимая ситуация (компилятор удаляет адреса функций в приведенном выше случае для того же кода, но при перемещении в статическую библиотеку)?

2) Как заставить компилятор всегдасохранить адреса функций-членов?

1 Ответ

0 голосов
/ 31 января 2019

Приношу свои извинения, я не нашел проблем с адресами функций указателей на члены в Visuals Studio.Указатели на виртуальные функции базового интерфейса разрешаются нормально, даже если они помещены в статическую библиотеку.Причины моих проблем были:

1) Отладчик иногда отображает адреса функций шаблонных классов как нули

2) Причиной сбоев было то, что основной проект имел / vmg вариант компилятора, но я пропустил его в проекте статической библиотеки.В таком случае следует быть осторожным с использованием / vmg всегда во всех ссылочных проектах библиотеки (сложности из-за этого - другая тема).

В любом случае, используя функции указателей на члены вместе суказатель объекта обычно является признаком плохого базового дизайна.

Я надеюсь, что это может кому-то помочь.

...