Müssen 3rd Party Bibliotheken mit dem exakt gleichen Compiler gebaut werden?



  • Hallo zusammen,

    wenn ich z.B. Qt einsetzte, dann gibt es für unterschiedliche Compiler eine Vorkompilierte Variante, wie z.B. für Microsoft Visual Studio 2013.

    Würde ich jetzt auf den Intel Compiler (oder ein anderer) umsteigen, wäre es dann auch dringend erforderlich, dass ich Qt auch mit diesem Compiler kompiliere?

    Ich vermute schon das jetzt ein JA KLAR kommt, aber aus welchem Grund ist das so? Allerdings sollten doch, wie Funktionen aufgerufen werden aus einer DLL "standardisiert" sein - oder nicht?

    Wenn jemand dazu einen guten Link hat, lese ich mir auch diesen sehr gerne durch.

    Viele Grüße,

    Jakob



  • Pauschal lässt sich das nicht beantworten, allerdings ist es nicht "dringend erforderlich" - zumindest bei C++-Bibliotheken würde ich es jedoch dringend empfehlen 😉

    Im Fall von C-Bibliotheken, oder solchen die ein reines C-Interface anbieten ist es meistens unproblematisch, wenn die DLL-Datei mit einem anderen Compiler gebaut wurde: Die Funktions/Symbolnamen sind hier nicht compilerspezifisch dekoriert (Name Mangling) und der Datenaustausch mit der Bibliothek läuft meist mit primitiven Datentypen (int, char* oder bibliotheksspezifischen struct s mit bekanntem Speicherlayout).

    Bei C++-Bibliotheken wie Qt läuft das jedoch etwas anders. Mögliche Probleme, die hier auftreten können:

    Name Mangling: In C++ ist es z.B. möglich dass mehrere Funktionen/Typen den selben Namen haben (überladene Funktionen, Namespaces, Templates, etc.), innerhalb einer DLL müssen die Symbolnamen jedoch eindeutig sein. Daher "dekorieren" C++-Compiler diese Namen indem sie darin zusätzliche Informationen einkodieren. Das Schema, dass dabei verwendet wird kann sich zwischen den Compilern sowie auch zwischen verschiedenen Versionen des selben Compilers unterscheiden, was meist dazu führt, dass der Linker diese Symbole nicht finden kann (wer kennt sie nicht, die schönen "unresolved referece"-Meldungen? ... nur diesmal obwohl man die korrekte Bibliothek dazu gelinkt hat).
    Inkompatible ABI: Name Mangling-Probleme sind noch relativ harmlos, eklig wirds wenn alles problemlos gebaut wird, aber die mit der Bibliothek ausgetauschten Objekte nicht binärkompatibel sind. Einfaches Beispiel: Eine Bibliotheksfunktion möchte z.B. einen std::string als Parameter haben und wurde mit Compiler A und dessen Standrardbibliothek kompiliert. Dein Programm verwendet aber Compiler B und eine ganz andere Standardbibliothek (eben die von Compiler B). Nun erzeugst du in deinem Programm std::string -Objekte mit dem Speicherlayout und den Funktionen aus Standardbibliothek B und übergibst sie an die Bibliothek. Allerdings übergibst du eigentlich keinen String sondern lediglich einen Klotz aneinandergereihte Bytes, der von der Bibliothek freudig als (vermeintlicher) std::string entgegengenommen, und dann mit den völlig falschen Methoden und Funktionen (aus Standardbibliothek A) weiterverarbeitet wird - wenn du Glück hast führt das schnell zu einem Crash, wenn du Pech hast schleicht sich dabei ein sehr subtiler Fehler in das Programm ein, der ausgiebiges Haareraufen zur folge haben kann :D.
    (Habe selbst schon diesbezüglich Spass mit Qt gehabt und der QString::fromStdString -Methode: Dabei war es noch nichtmal ein anderer Compiler, sondern lediglich eine Debug-Variante von Qt, mit der ich versehentlich eine Release-Version meines Programms gebaut habe. Da hat die String-Klasse in der Debug-Version vielleicht noch irgendwo einen zusätzlichen Member eingeschoben, der dann zu einem völlig anderen Speicherlayout führt, so dass dann z.B. die ersten Buchstaben des Strings als Länge interpretiert werden o.ä.).
    Andere Probleme: z.B. Unterschiedliche Exception Handling-Methoden können auch zu Problemen führen, besonders wenn einem aus der DLL Exceptions entgegengeflogen kommen, und der neue Compiler keine Ahnung hat wie er in einem solchen Fall den Stack wieder aufzuräumen hat (weil er z.B. das Exception-Handling-Modell von Visual Studio nicht unterstützt).

    TL;DR: Kann funktionieren mit einem anderen Compiler, muss aber nicht und kann teilweise zu Fehlern führen, denen man nur sehr schwer auf die Schliche kommt. Die Chancen stehen allerdings besser, wenn der neue Compiler wert darauf legt, zu MSVC kompatibel zu sein - bei ICC weiss ich nicht allzu viel darüber, Clang mit seinem MSVC "driver" (clang-cl) kommt damit mittlerweile jedoch relativ gut klar (verwendet dann aber auch die MSVC-Standardbibliothek).
    Wenn man alles mit dem selben Compiler baut, spart man sich jedoch meist eine Menge Kopfschmerzen (allerdings ist Qt auch ein ganz schöner Moloch wenn man es selbst bauen will).

    Gruss,
    Finnegan



  • Hallo Finnegan,

    vielen Dank für Deine ausführliche Antwort mit einleuchtenden Beispiele.

    Viele Grüße,

    Jakob


Anmelden zum Antworten