In meiner shared library muss ich eine bestimmte Initialisierung zur Ladezeit durchführen. Wenn ich die Funktion mit dem GCC-Attribut __attribute__ ((constructor))
definiere, funktioniert es nicht, d.h. es wird nicht aufgerufen, wenn das Programm, das meine gemeinsam genutzte Bibliothek verbindet, geladen wird.
Wenn ich den Funktionsnamen in _init()
ändere, funktioniert es. Offenbar sind die Funktionen _init()
und _fini()
nicht empfohlen jetzt.
Irgendeine Idee warum __attribute__ ((constructor))
nicht funktionieren würde? Dies ist mit Linux 2.6.9, gcc
Version 3.4.6
Bearbeiten:
Nehmen wir beispielsweise an, dass der Bibliothekscode Folgendes ist:
%Vor%Für den Aufbau der .so mache ich folgendes:
%Vor% Da sich die .so nicht an einem der Standardstandorte befindet, aktualisiere ich den LD_LIBRARY_PATH
und verbinde den .so von einem anderen Programm. Der Konstruktor wird nicht aufgerufen. Wenn ich es in _init()
ändere, funktioniert es.
Okay, also ich habe mir das angesehen und es sieht so aus, als ob der intermediate gcc
-Schritt (mit -c
) das Problem verursacht. Hier ist meine Interpretation von dem, was ich sehe.
Wenn Sie als .o
mit setup()
kompilieren, behandelt gcc
sie nur als normale Funktion (da Sie nicht als .so
kompilieren, ist das also egal). Dann sieht ld
in der dynamischen Sektion der ELF keine _init()
oder irgendetwas wie DT_INIT
und geht davon aus, dass es keine Konstruktoren gibt.
Wenn Sie als .o
mit _init()
kompilieren, behandelt gcc
sie auch als normale Funktion. In der Tat sieht es für mich aus wie die Objektdateien sind identisch mit Ausnahme der Namen der Funktionen selbst! Also noch einmal, ld
schaut auf die .o
-Datei, aber diesmal sieht sie eine _init()
-Funktion, die sie sucht und entscheidet, dass es ein Konstruktor ist, und erstellt dementsprechend einen DT_INIT
-Eintrag in der neuen .so
.
Schließlich, wenn Sie das Kompilieren und Verknüpfen in einem Schritt machen, wie folgt:
%Vor% Dann passiert, dass gcc
das __attribute__ ((constructor))
im Zusammenhang mit der Erstellung eines gemeinsamen Objekts sieht und versteht und dementsprechend einen DT_INIT
-Eintrag erstellt.
Kurzversion: Verwenden Sie gcc
zum Kompilieren und Linken in einem Schritt. Sie können -Wl
verwenden (siehe die man-Seite), um zusätzliche Optionen wie -soname
, falls erforderlich, wie -Wl,-soname,libsmlib.so.1
zu übergeben.
Von diesem Link :
"Gemeinsam genutzte Bibliotheken dürfen nicht mit den gcc-Argumenten -nostartfiles 'oder -nostdlib' kompiliert werden. Wenn diese Argumente verwendet werden, werden die Konstruktor- / Destruktor-Routinen nicht ausgeführt (sofern keine besonderen Maßnahmen getroffen werden)."
gcc / ld setzt das DT_INIT-Bit im Elf-Header nicht, wenn -nostdlib verwendet wird. Sie können objdump -p überprüfen und in beiden Fällen nach dem Abschnitt INIT suchen. In Attribut ((Konstruktor)) finden Sie diesen INIT-Abschnitt nicht. Aber für __init Fall finden Sie INIT-Abschnitt in der gemeinsam genutzten Bibliothek.
Tags und Links c gcc linux shared-libraries