2016-05-21 3 views
3

Der folgende Testfall, der von einer realen Anwendung reduziert wurde, kann nicht mit -fsanitize=undefined (unter Verwendung von GCC 6.1.1) verlinkt werden, aber es funktioniert gut ohne es. Kann mir jemand sagen warum?Warum -fanitize = undefinierte Ursache "undefinierter Verweis auf Typinfo"?

Es scheint, etwas zu haben, die mit der Kombination von Qt/QObject, -fvisibility=hidden und -fsanitize=undefined, aber genau dort, wo das Problem liegt, ist mir zu tun.

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(); 
} 

Erstellungsschritte:

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-Ausgabe (aus dem letzten Schritt):

/tmp/ccY7PHv4.o:(.data.rel+0x18): undefined reference to `typeinfo for MyObject' 
collect2: error: ld returned 1 exit status 

Antwort

2

Ich denke, die -fsanitize=undefined eine falsche Fährte ist.

Sie exportieren nur die Mitgliedsfunktionen dieser Klasse. Um auch seine Metadaten (wie typefinfo und potentieller v-Tabellenzeiger) zu exportieren, müssen Sie die Klasse exportieren.

Versuchen Sie, diese

class EXPORT MyObject : public QObject 
{ 
public: 
    MyObject (QObject * parent = nullptr); 
    ~MyObject(); 

    void myMethod(); 
}; 

Dann sollten Sie nicht die einzelnen Mitgliederfunktionen markieren müssen.

+0

sagen kann ..., die ein wenig mehr Mühe bedeutet, da jetzt die EXPORT im öffentlichen Header definiert werden muss, und muss wechseln zwischen dllimport und dllexport für die Windows-Builds. Aber ich habe etwas mehr gelesen, und das scheint der empfohlene Weg zu sein. –

+0

Ich glaube, dass Sie das unabhängig von Windows benötigen würden, da es Symbolnamen verziert. siehe http://stackoverflow.com/questions/3704374/linking-error-lnk2019-in-msvc-unresolved-symbols-with-imp-prefix-but-shoul – Arvid

+0

Definiere "need". :) Richtig oder nicht, wir haben diese Anwendung unter Windows seit Jahren ohne irgendeine Art von dllimport/dllexport in den öffentlichen Headern erstellt. Das Markieren einzelner Funktionsimplementierungen, wie im Beispiel, war genug, um alles kompilieren und laufen zu lassen. –

1

Die Antwort auf die eigentliche Frage ist, dass -fsanitize=undefined ist eigentlich eine Sammlung von Sanitizers einschließlich der vptr Sanitizer.

https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html

Die vptr Sanitizer ist als erforderlich RTTI info eindeutig gekennzeichnet, die anderen Antworten beschrieben haben, warum es nicht verfügbar ist.

Um alle Tests außer vptr laufen, Sie

-fsanitize=undefined -fno-sanitize=vptr 
Verwandte Themen