Почему -fsanitize=undefined вызывает "неопределенную ссылку на typeinfo"?
Следующий тестовый пример, исключенный из реального приложения, не может связаться с -fsanitize=undefined
(с использованием GCC 6.1.1), но ссылки без него нормально. Кто-нибудь может сказать мне, почему?
Похоже, что-то связано с комбинацией Qt / QObject, -fvisibility=hidden
, а также -fsanitize=undefined
, но именно в чем проблема лежит вне меня.
lib1.h:
#include <QObject>
class MyObject : public QObject
{
public:
MyObject (QObject * parent = nullptr);
~MyObject ();
void myMethod ();
};
lib1.cc:
#include "lib1.h"
#define EXPORT __attribute__((visibility("default")))
EXPORT MyObject::MyObject (QObject * parent) : QObject (parent)
{
}
EXPORT MyObject::~MyObject ()
{
}
EXPORT void MyObject::myMethod ()
{
}
lib2.cc:
#include "lib1.h"
void test (MyObject * object)
{
object->myMethod ();
}
Построить шаги:
LIBFLAGS="-fPIC -shared -Wall -Wl,-z,defs"
QTFLAGS="-I/usr/include/qt -I/usr/include/qt/QtCore -lQt5Core"
g++ -fsanitize=undefined -fvisibility=hidden \
${QTFLAGS} ${LIBFLAGS} lib1.cc -o lib1.so
g++ -fsanitize=undefined \
${QTFLAGS} ${LIBFLAGS} lib1.so lib2.cc -o lib2.so
Построить вывод (из последнего шага):
/tmp/ccY7PHv4.o:(.data.rel+0x18): undefined reference to `typeinfo for MyObject'
collect2: error: ld returned 1 exit status
2 ответа
Я думаю -fsanitize=undefined
красная сельдь
Вы экспортируете только функции-члены этого класса. Чтобы также экспортировать его метаданные (такие как typeinfo и потенциальный указатель на v-таблицу), вам необходимо экспортировать класс.
Попробуй это
class EXPORT MyObject : public QObject
{
public:
MyObject (QObject * parent = nullptr);
~MyObject ();
void myMethod ();
};
Тогда вам не нужно размечать отдельные функции-члены.
Ответ на заданный вопрос заключается в том, что -fsanitize=undefined
на самом деле коллекция дезинфицирующих средств, включая vptr
дезинфицирующее.
https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
vptr
sanitizer четко помечен как требующий информации RTTI, в других ответах описано, почему он недоступен.
Чтобы запустить все тесты, кроме vptr, вы можете сказать,
-fsanitize=undefined -fno-sanitize=vptr