#c #eclipse #dll #segmentation-fault #eclipse-cdt
#c #eclipse #dll #ошибка сегментации #eclipse-cdt
Вопрос:
в приложении, которое я пишу, я динамически загружаю объекты из созданной мной общей библиотеки.
Это нормально до того момента, когда в игру вступают виртуальные функции. Это означает, что я могу легко вызывать средства получения и установки, но я сразу же получаю ошибку сегментации при попытке вызвать функцию, которая перезаписывает функции виртуального базового класса. В настоящее время у меня заканчиваются идеи, поскольку это происходит с каждым классом (иерархией) в моем проекте.
Функции могут быть успешно вызваны при создании объектов внутри приложения, вообще не используя динамическую загрузку или разделяемые библиотеки.
Я подозреваю либо концептуальную ошибку, либо какую-то ошибку компиляции / компоновки на моей стороне.
Иерархия классов выглядит примерно так:
BaseClass.h:
class BaseClass : public EvenMoreBaseClass {
public:
virtual bool enroll(const shared_ptr<string> filepath) = 0;
}
Derived.h:
class Derived : public BaseClass {
bool enroll(const shared_ptr<string> filepath);
}
Derived.cpp:
bool Derived::enroll(const shared_ptr<string> filepath) {
cout << "enroll" << endl;
}
(включает и пространство имен, оставленное здесь)
Приложение загружает библиотеку и получает (общий) указатель на объект базового класса (приложение включает BaseClass.h). Могут выполняться все функции, кроме виртуальных.
Разработка выполняется в Eclipse CDT. В настоящее время все находится в одном проекте с разными конфигурациями сборки (.cpp приложения отключен в конфигурации разделяемой библиотеки и наоборот). Компилятором является g 4.4. Все файлы .o иерархии связаны с библиотекой, — установлено значение shared.
Я был бы действительно признателен за любую помощь.
Комментарии:
1. Вы запускали это в отладчике?
2. У меня есть, но я просто получаю segfault при второй попытке доступа к виртуальной функции. Я установил точку останова для имени виртуальной функции, но она никогда не вызывается успешно в библиотеке.
Ответ №1:
Возможно, это очень поздний ответ, но я обнаружил такое же поведение, это происходит, если вы используете dlclose(handle)
перед доступом к виртуальному методу (хотя статические методы работали корректно). Поэтому вам не следует закрывать дескриптор библиотеки, пока вы не закончите с объектами из нее.
Ответ №2:
Убедитесь, что dll и исполняемый файл компилируются с точными одинаковыми настройками компилятора. Если они отличаются, компилятор может генерировать код в исполняемом файле, который не соответствует тому, что ожидает dll, и наоборот, что является нарушением ODR.
Обратите внимание, что стандартные типы библиотек, такие как std::string и std::shared_ptr, могут иметь разные макеты, например, в конфигурациях отладки, а также могут меняться между версиями компилятора (даже от одного и того же поставщика).
В общем, вам нужно быть осторожным, используя классы за пределами dll. Обычно рекомендуется иметь дело только со встроенными типами и интерфейсами без состояния.
Ответ №3:
Может ли быть какая-либо разница в размерах типов между проектами, установленными в конфигурациях сборки?
[обновление]
Я сталкивался с подобными проблемами, когда в одном проекте такие типы, как short и long, определены как отличающиеся по размерам от другого проекта, и на классы, содержащие эти типы, ссылаются через один и тот же заголовочный файл. Один проект помещает второе сокращение в байт 2, другой проект считает, что оно находится в байте 4.
У меня также были проблемы с различными значениями заполнения. Один проект дополняет нечетные символы границами в 4 байта, другой считает, что он дополнен границами в 8 байт.
То же самое может быть справедливо и для указателей виртуальных функций, возможно, один проект умещает их в 32 бита, другой ожидает их в 64 бита.
Комментарии:
1. Они включают одни и те же файлы, и я обычно компилирую обе конфигурации. Может ли это быть проблемой, например, одна сборка создает разные файлы .o, чем другая, что приводит к разным типам для библиотеки и приложения? Или вы имеете в виду какие-то другие размеры типов?
2. Спасибо за обновление, я проверю это, когда вернусь к проблеме — поскольку динамическая загрузка в этом проекте скорее «приятная функция», я сначала сосредоточусь на логике приложения.