C ++: виртуальные функции в динамической разделяемой библиотеке производят segfault - PullRequest
2 голосов
/ 10 ноября 2011

в приложении, которое я пишу, я динамически загружаю объекты из общей библиотеки, которую я написал.

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

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

Я подозреваю либо концептуальную ошибку, либо какую-то ошибку компиляции / компоновки на моей стороне.

Иерархия классов выглядит примерно так:

BaseClass.h:

class BaseClass : public EvenMoreBaseClass { public: virtual bool enroll(const shared_ptr<string> filepath) = 0; }

Производные.h:

class Derived : public BaseClass { bool enroll(const shared_ptr<string> filepath); }

Производные.cpp:

bool Derived::enroll(const shared_ptr<string> filepath) { cout << "enroll" << endl; }

(включает и пространство имен здесь опущено)

Приложение загружает библиотеку и получает (общий) указатель на объект BaseClass (приложение включает BaseClass.h).Все функции могут быть выполнены, кроме виртуальных.

Разработка выполняется в Eclipse CDT.В настоящее время все находится в одном проекте с различными конфигурациями сборки (.cpp приложения отключен в конфигурации общей библиотеки и наоборот).Компилятор g ++ 4.4.Все .o файлы иерархии связаны с библиотекой, установлен -shared.

Буду очень признателен за любую помощь.

Ответы [ 3 ]

0 голосов
/ 11 ноября 2011

Убедитесь, что dll и исполняемый файл скомпилированы с точными одинаковыми настройками компилятора. Если они отличаются, компилятор может генерировать код в исполняемом файле, который не соответствует ожидаемому dll, и наоборот, что является нарушением ODR .

Обратите внимание, что стандартные типы библиотек, такие как std :: string и std :: shared_ptr, могут, например, иметь разные макеты в конфигурациях отладки, а также могут меняться между версиями компилятора (даже от одного и того же поставщика).

В общем, вы должны быть осторожны, используя классы за пределами dll. Обычно рекомендуется работать только со встроенными типами и интерфейсами без сохранения состояния.

0 голосов
/ 15 сентября 2015

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

0 голосов
/ 10 ноября 2011

Может ли быть какая-либо разница в размерах типов между проектами, установленными в конфигурациях сборки?

[update]

Я сталкивался с подобными проблемами, когда в одном проекте есть такие типы, как shortи long определены как размеры, отличающиеся от другого проекта, а классы, содержащие эти типы, ссылаются через один и тот же заголовочный файл.Один проект помещает второе короткое в байт 2, другой проект думает, что это в байте 4.

У меня также были проблемы с различными значениями заполнения.Один проект добавляет нечетные символы к 4-байтовым границам, другой думает, что он дополняется 8-байтовыми границами.

То же самое можно сказать и о виртуальных указателях функций, возможно, один проект умещает их в 32-битные, другой ожидает ихв 64 битах.

...