Wir haben eine große Open-Source-Software auf einer Vielzahl von Plattformen (Linux, Windows, Mac OS X, 32-Bit und 64-Bit) für mehrere Jahre ohne Probleme. In letzter Zeit jedoch hat die Mac OS X Build (64-Bit) nicht mehr korrekt funktioniert und stürzte wahllos ab. Es stimmte mehr oder weniger mit einem Update von Mac OS X auf unserer Build-Maschine von 10.7 auf 10.8.2 überein (aber die Compiler-Toolchain änderte sich nicht, es ist immer noch llvm-gcc 4.2.1).
Unsere Anwendung besteht aus ein paar dynamischen (geteilten) Bibliotheken und vielen ausführbaren Dateien, die diese benutzen. Eine der gemeinsam genutzten Bibliotheken überschreibt die Operatoren new
und delete
aus verschiedenen Gründen. Unter Mac OS X (und Linux) werden standardmäßig alle Symbole exportiert, einschließlich unserer überladenen Operatoren new
und delete
. Die Abstürze unter Mac OS X scheinen auf Speicher zurückzuführen zu sein, der mit einem Speichersubsystem (nicht unserem) zugewiesen wurde und dann durch unsere eigene (und inkompatible) delete
-Implementierung freigegeben wurde.
Die klarste Lösung scheint zu verhindern, dass die überladenen Operatoren für die Benutzer der gemeinsam genutzten Bibliothek sichtbar sind. Dies kann auf zwei Arten erfolgen: Markieren der Operatoren mit __attribute__((visibility("hidden")))
oder Verwenden der Befehlszeilenoption -unexported_symbols_list
linker, um zu verhindern, dass einige Symbole exportiert werden. Die erste Lösung funktioniert leider nicht: gcc gibt Warnungen aus, dass die Operatoren anders deklariert wurden (in <new>
) und somit die Attribute ignoriert werden. Aus meinen Lesungen an verschiedenen Orten scheint die zweite Lösung die richtige für dieses Problem zu sein. Aus irgendeinem Grund können wir es jedoch nicht schaffen .
Wenn Sie die gemeinsam genutzte Bibliothek verknüpfen, übergeben wir die Option -Wl,-unexported_symbols_list unexported_symbols_list.txt
an g ++, die wiederum an ld übergeben werden soll. Die Datei unexported_symbols_list.txt
enthält die folgende Symbolliste:
Dies sind alle Variationen von new
und delete
, die wir überschreiben und die ausgeblendet werden sollen. Wir haben diese Symbole gefunden, indem wir nm libappleseed.dylib
gemacht haben und dann die Symbolnamen mit c++filt
entfernt haben.
Hier ist die Befehlszeile, die von CMake generiert wurde, um libappeseed.dylib
:
Leider scheint es, trotz all unserer Bemühungen, dass die Symbole erhalten bleiben (wie nm zeigt).
Irgendeine Idee, was wir falsch machen? Gibt es einen anderen Ansatz, den wir ausprobieren könnten?
UPDATE Dez. 19, 2012:
Unser Problem und die vermeintliche Lösung sind in dieser technischen Anmerkung von Apple gut beschrieben: Ссылка (Abschnitt "Überschreiben / Löschen").
Zeiger auf relevanten Quellcode:
operator new
Überschreibungen: allocator.cpp
Fragment der Ausgabe von operator delete
nach dem Erstellen von libappleseed.dylib mit nm
und laufendem -fvisibility=hidden
:
Tags und Links c++ macos shared-libraries new-operator gnu