недавно мы столкнулись в нашем унаследованном коде, который в настоящее время портирован с 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;
};
processFoo () будет вызываться с различными реализациями IFoo. Некоторые из dll A, а некоторые из dll B.
Теперь произошло следующее:
— если мы включили оптимизацию всей программы при компиляции dll B, вызов виртуальной функции GetSlot () в функции fill () был де-виртуализирован Visual C ++. Это вызвало сбой нашей программы.
мы можем исправить это поведение, если мы либо
У меня есть следующие вопросы:
Спасибо за помощь
Тобиас
Использование LTO приводит к тому, что компилятор вносит радикальные коррективы в любые функции, для которых он может видеть полный список вызовов.
То, что вы видите, ожидается и использует __declspec(dllexport)
или же extern
на функциях, которые необходимо использовать из отдельного модуля или явно объявить их как часть DLL-файла .def, — это ожидаемый способ решения проблемы, так как компилятор больше не будет считать функции только внутренними.
Других решений пока нет …