The following test-case, reduced from a real-world application, fails to link with -fsanitize=undefined
(using GCC 6.1.1) but links fine without it. Can anyone tell me why?
It seems to have something to do with the combination of Qt/QObject, -fvisibility=hidden
, and -fsanitize=undefined
, but exactly where the problem lies is beyond me.
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 ();
}
Build steps:
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
Build output (from the final step):
/tmp/ccY7PHv4.o:(.data.rel+0x18): undefined reference to `typeinfo for MyObject'
collect2: error: ld returned 1 exit status
I think the -fsanitize=undefined
is a red herring.
You are only exporting the member functions of that class. In order to also export its metadata (like its typeinfo and potential v-table pointer) you need to export the class.
Try this
class EXPORT MyObject : public QObject
{
public:
MyObject (QObject * parent = nullptr);
~MyObject ();
void myMethod ();
};
Then you should not need to mark up the individual member functions.