8 Stimmen

Wie kann man eine Anwendung erstellen, die sowohl libstdc++.so.5 als auch libstdc++.so.6 benötigt?

Ich möchte dies mit dem wichtigen Hinweis einleiten, dass Ich bin kein C/C++-Programmierer und wissen sehr gering darüber, wie die Verknüpfung von Bibliotheken in C funktioniert.

Unser Code verwendet libstdc++.so.6 (gcc 3.4, glaube ich). Wir haben Drittanbieter vorkompiliert (geschlossene Quelle) Bibliotheken, die libstdc++.so.5 (gcc 2.etwas oder 3.2, ich glaube) verwenden. Dies ist auf Linux. Wir haben sowohl eine .a- als auch eine .so-Version der Drittanbieter-Bibliothek.

Ist es möglich, unsere Anwendung mit den Bibliotheken von Drittanbietern zu erstellen? Wie? Ist es möglich, unsere App zu erstellen/auszuführen, ohne dass libstdc++.so.5 auf unseren Rechnern installiert ist, wie?

Sollte ich eine wichtige Information vergessen haben, lassen Sie es mich bitte wissen - ich weiß kaum, was bei diesem Zeug relevant ist. Mir ist klar, dass eine vollständige Antwort wahrscheinlich nicht möglich sein wird; ich bin wirklich auf der Suche nach Orientierung und Anleitung. Statischer Link dies, dynamischer Link das, Rebuild das, Prebuild dies und das, Wechsel zu Version x, oder Symlink das Quizdoodle, etc.

Aktualisierung:

Wir haben es mit dlopen avec RTLD_LOCAL um die Bibliothek des Drittanbieters vom Rest unserer Anwendung zu isolieren. Dies scheint zu haben meist gearbeitet hat, bleiben jedoch aus unbekannten Gründen große Speicherlecks zurück. Wir vermuten, dass wir beim Aufruf von dlopen zieht die Bibliothek von Drittanbietern Symbole ein wie malloc aus der bereits geladenen .so.6, und die Dinge geraten durcheinander.

Aus Jux und Dollerei haben wir versucht, die Drittanbieter-Bibliothek in LD_PRELOAD und dann unsere Anwendung ausgeführt, und die Speicherlecks scheinen vollständig zu verschwinden.

0 Stimmen

Ich kann mir nicht helfen, aber ich habe das Gefühl, dass Namespaces zur Lösung dieses Problems beitragen könnten. Da der Anbieter seine Bibliothek nicht reparieren will, ist es möglich, dass er seine Sachen in einen zusätzlichen Namespace stellt, wie namespace 5 {} . Das heißt, ihre Bibliothek würde die 5::malloc , während für die aktuellen Sachen nur die malloc . (Ich weiche einigen Fragen aus, z. B. warum sie die malloc in einem C++-Programm).

7voto

pobedim Punkte 491

Sie können versuchen, eine Wrapper-Bibliothek um Ihre 3rd-Party-Bibliothek herum zu bauen: Verwenden Sie die statische Version dieser Bibliothek und verknüpfen Sie sie mit der statischen Standardbibliothek (-static-libgcc - stellen Sie sicher, dass Sie eine korrekte Version über -L abrufen). Das Wichtigste ist, diese Wrapper-Bibliothek richtig zu schließen, d.h. nur Symbole aus der ursprünglichen 3rd-Party-Bibliothek sollten exportiert werden, alles andere sollte versteckt werden. Auf diese Weise wird Ihre Wrapper-Bibliothek alle benötigten Symbole für Ihre Anwendung bereitstellen und die Standard-Symbole darin kapseln. Beachten Sie, dass es nicht garantiert ist, dass es funktioniert, insbesondere wenn einige Speicheroperationen zwischen Ihrem Code und dem Code des Drittanbieters geteilt werden (z.B. Sie weisen Speicher in Ihrem Code zu und geben ihn in dem des Drittanbieters frei)... in einem solchen Fall kann die einzige Option sein, diese Bibliothek des Drittanbieters in einem anderen Prozessraum zu halten.

Ich glaube nicht, dass die oben erwähnte dynamische Option funktionieren würde, da Sie genau das gleiche Problem haben werden - nur später.

Im Allgemeinen ist es besser, Binärdateien mit unterschiedlichen Laufzeiten nicht im selben Prozessraum zu mischen. Das ist fast immer ein Rezept für eine Katastrophe.

0 Stimmen

Können Sie erklären, wie man die Symbole richtig versteckt, und was Sie über die Speicheroperationen sagen? Wir haben versucht, die Drittanbieter-Lib in Funktionen zu verpacken, die dlopen(lib, RTLD_LOCAL) verwenden, um die Drittanbieter-Lib zu laden. Dies verhinderte, dass unser Code in .so.5 gelinkt wurde, aber wir vermuteten, dass der Code des Drittanbieters Symbole (wie z.B. malloc) aus dem bereits geladenen .so.6 (das von unserem Code geladen wurde) aufnahm und Speicherlecks verursachte. Wir haben versucht, mit LD_PRELOAD die 3rd-Party-Lib zuerst zu laden, und die Speicherlecks waren so gut wie verschwunden.

0 Stimmen

Und wir tun auf unserer Seite allokieren, und die Drittanbieter-Lib deallokiert. z.B.: ThirdPartyStruct * foo = malloc(...); ThirdPartyApiCall(foo); ThirdPartyFreeStruct(foo); - Willst du damit sagen, dass das einfach nicht möglich ist, wenn wir .6 verwenden und die Drittanbieter-Lib .5 verwendet? Was wäre, wenn wir .5 mit unseren Wrapper-Funktionen verwenden und alle Zuweisungen/Deallokationen über die Wrapper-Lib vornehmen würden?

0 Stimmen

Wenn Allokation/Deallokation in verschiedenen Standardbibliotheken durchgeführt wird, kann man nicht sicher sein, dass sie dies auf die gleiche Weise tun... man weiß es einfach nicht. Ich kann nicht sagen, ob es unter Linux ein echtes Problem ist, aber unter Windows ist es das definitiv: Wenn Sie verschiedene Laufzeiten in Ihren Bibliotheken verwenden und die Allokation in einer und die Deallokation in einer anderen durchführen, erhalten Sie eine Laufzeitausnahme. Ich würde nicht einmal erwägen, verschiedene Standardbibliotheken in Ihrem Fall zu mischen, selbst wenn es auf dieser bestimmten Plattform mit diesen bestimmten Laufzeiten funktioniert, können Sie nicht sicher sein, dass es funktioniert, wenn Sie zu einer neuen Version von libstd wechseln...

4voto

Steven Schlansker Punkte 35955

Bitten Sie Ihren Anbieter um eine neuere Version der Bibliothek, die etwas verwendet, das nicht völlig veraltet ist. Andernfalls könnten Sie prüfen, ob Ihre neue Anwendung noch mit der älteren Version der Bibliothek funktioniert und sie gegebenenfalls zurückportieren. Wenn Sie versuchen, zwei verschiedene Versionen derselben Bibliothek zu verwenden, ist das sehr problematisch, und ich glaube nicht, dass Sie eine akzeptable Lösung finden werden.

0 Stimmen

Der Anbieter sträubt sich sehr dagegen, seine Bibliothek zu aktualisieren (wir streiten uns schon seit Wochen). Die Anwendung kann nicht auf .so.5 zurückportiert werden

2voto

Martin Punkte 21

Es ist zwar einfach, sowohl libstdc++.so.6 als auch libstdc++.so.5 gleichzeitig mit Ihrer Anwendung zu verknüpfen, aber das Verhalten wird so gut wie undefiniert sein, da Symbole aus beiden Bibliotheken im Grunde zufällig übernommen werden.

Der beste Weg zum Erfolg ist IMO eine eigene Anwendung um Ihre 3rd-Party-Lib auf einem alten System (die mit einem kompatiblen gcc wie z. B. gcc 3.3) zu bauen, und lassen Sie es mit Ihrer Hauptanwendung über IPC (z. B. Shared Memory) kommunizieren. Auf diese Weise wird keine

Wenn Sie libstdc++.so.5 nicht auf Ihrem Zielsystem behalten wollen, dann ist das ganz einfach: Verwenden Sie das -static-Flag von gcc, um libstdc++.a mit Ihrer Wrapper-Anwendung zu linken.

0 Stimmen

Ich habe eine ähnliche Frage gefunden, und eine der Antworten deutet darauf hin, dass durch eine Art dynamische Verknüpfungsmagie beides ohne Probleme möglich ist. Ist das wahr, oder eine Fehlinformation? stackoverflow.com/questions/728858/

1voto

Michael Ekstrand Punkte 27071

Während einer der bisher genannten Ansätze funktionieren könnte, halte ich es für sicherer zu sagen, dass Sie dies nicht direkt auf zuverlässige Weise tun können. Wenn Sie einen Wrapper schreiben, der ausschließlich C-basierte APIs verwendet (nur C-kompatible Strukturen, von malloc/free verwalteter Speicher, usw.), dann können Sie vielleicht die Lösung von pobedim verwenden. Wenn Sie jedoch C++-Strukturen austauschen müssen, ist dies nicht sicher, da, selbst wenn Sie die Verknüpfung herstellen könnten, unterschiedliche Standardbibliotheksimplementierungen für dieselben Objekte verwendet würden. Außerdem kann es sein, dass die C++ ABI zwischen .5- und .6-basierten Codebasen nicht kompatibel ist (ich weiß nicht mehr genau, wie die große Gnu C++ ABI-Änderung vor ein paar Jahren in Bezug auf die Standardbibliotheks-Sonames abgelaufen ist).

Ich denke, der sicherste Ansatz zur Lösung dieses Problems ist die Verwendung eines Multiprozess-Ansatzes mit einer Art von IPC zwischen Ihrer Anwendung und einem Ressourcen-/Computing-Server-Prozess, der auf der betreffenden Bibliothek aufbaut. Sie könnten CORBA, D-Bus, Sun RPC oder ein Ad-hoc-Protokoll über Pipes oder Sockets verwenden, um diese Aufgabe zu erledigen. Ich habe dies getan, als ich versuchte, 32-Bit-Code aus geschlossenem Quellcode in 64-Bit-Anwendungen zu verwenden, und es funktioniert gut genug. Sie werden einen Leistungseinbruch feststellen, aber Sie umgehen auch die Probleme, die mit dem Versuch verbunden sind, C++-Laufzeiten in einem einzigen Prozess zu mischen.

1 Stimmen

Ich kann bestätigen, dass die Lösung von pobedim für eine C-basierte API funktioniert. Solange nur reine C-Symbole aus dem Wrapper exportiert werden, gibt es keine Abstürze.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X