Почему -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
Другие вопросы по тегам