Was ist falsch daran, die STL statisch in mehrere gemeinsam genutzte Bibliotheken zu verknüpfen?

8

Hier ist das Szenario:

  1. libA.so und libB.so sind beide statisch mit derselben STL verknüpft.
  2. libA.so verfügt über eine öffentliche API, die einen std :: string zurückgibt.
  3. libB.so ruft diese Funktion auf und erhält eine Kopie der Zeichenfolge.
  4. Wenn die Kopie der Zeichenfolge von libB.so den Gültigkeitsbereich verlässt, wird der Destruktor der Zeichenfolge aufgerufen.
  5. Die Anwendung seg Fehler beim Versuch, die kopierte Zeichenfolge freizugeben.

Ich habe an anderer Stelle gelesen, dass eine solche statische Verknüpfung schlecht ist, aber ich möchte besser verstehen, warum sie schlecht ist. Kann jemand erklären, warum die obige Sequenz abstürzen würde?

user1509041
quelle

Antworten:

8

Lassen Sie uns sehr sorgfältig darüber nachdenken. libA.so ist statisch mit der STL verknüpft. Die STL existiert jedoch nicht isoliert, sondern erfordert die C-Laufzeit (CRT). Beide befinden sich in der statischen Bibliothek libstdc ++. Dies bedeutet, dass libA.so und libB.so separate CRT-Datenstrukturen haben. Insbesondere unterscheidet sich der von libA.so verwendete Heap von dem von libB.so verwendeten Heap. Das Zuweisen einer Zeichenfolge aus dem Laufzeitheap von libA und der Versuch, die Laufzeit von libB freizugeben, funktionieren einfach nicht, da die Laufzeit von libB keine Datensätze zum Zuweisen der Zeichenfolge enthält. Die einzige Möglichkeit, die Zeichenfolge korrekt zu zerstören, besteht darin, den Destruktor in libA.so aufzurufen.

Man könnte fragen: aber libB.so erhält eine Kopie der Zeichenfolge, oder? Ja, das stimmt, aber wer hat diese Kopie zugewiesen? Es wurde mithilfe des Kopierkonstruktors im Kontext der Laufzeit der libA zugewiesen.

Sie können jedoch weiterhin die Zeichenfolge von libB.so verwenden. Von dort aus kann man es einfach nicht zerstören.

Sie können libB auch einen Zeiger auf die Zeichenfolge empfangen lassen und anschließend im Kontext der Laufzeit der libB eine Kopie davon erstellen. Diese Kopie kann von libB zerstört werden.

Und deshalb ist statische Verknüpfung manchmal schlecht.

Hadi Brais
quelle
1
Ich bin mir nicht sicher, worauf sich "String" hier bezieht. Wenn von a die Rede ist, besteht std::stringdas Problem einfach nicht: Entweder libB.soempfängt es eine Kopie der Zeichenfolge, wobei der Speicher in seinem eigenen Speicher verwaltet wird, oder es erhält eine Referenz / einen Zeiger auf die Zeichenfolge in libA.sound versucht nicht, sie zu entfernen die Zeichenfolge aus dem eigenen Speicher.
Konrad Rudolph
1
@KonradRudolph Unter anderem erzeugen (N) RVO-Optimierungen Situationen, in denen die zurückgegebene Zeichenfolge von libA.so erstellt und von libB.so zerstört wird.
Sjoerd
Diese Antwort stimmt mit dem überein, was ich in der Praxis gesehen habe. Ich denke, der Teil, den ich nicht vollständig verstehe, ist, wie der Heap für jede Bibliothek funktioniert. Anfangs dachte ich, der Heap sei eine einzigartige globale Sache in diesem Prozess, aber die Art und Weise, wie Sie ihn beschreiben, klingt so, als gäbe es mehrere Heaps. Geht es nur darum, wie die Allokatoren (in libc?) Implementiert werden, oder gibt es etwas anderes, das dies steuert (wie den Loader)?
user1509041
Ob ein Prozess einen globalen Heap oder mehrere Heaps enthält, hängt von der verwendeten spezifischen CRT-Implementierung ab. Ich habe beide Fälle gesehen. Sie scheinen mehrere Haufen zu haben. Der Lader hat nichts mit Haufen zu tun.
Hadi Brais
1
@ AymanSalah Ja, das sollte gut funktionieren. Die Betriebssystemversion ist nur wichtig, wenn Sie betriebssystemspezifische APIs anstelle von Sprachstandard-APIs verwenden.
Hadi Brais
3

Die STL ist so genannt "state-full" (im Gegensatz zu "state-less"), was bedeutet, dass sie einige statische Elemente enthält. Wenn Sie STL statisch mit libA.so und libB.so verknüpfen, erhalten Sie zur Laufzeit zwei Instanzen der STL-Bibliothek im Speicher (mit zwei Kopien statischen Materials). Jede dieser beiden Kopien verwaltet die zugewiesenen Ressourcen unabhängig voneinander, und die in einer Bibliotheksinstanz zugewiesenen Ressourcen können in einer anderen nicht freigegeben werden

mvidelgauz
quelle