sich das folgende triviale C-Programm,Was ist der richtige Weg, um eine thread-sichere, plattformübergreifende C-Bibliothek zu erstellen?
#include <errno.h>
int
main(int argc, char* argv[]) {
return errno;
}
Wenn auf Solaris kompiliert, das Verhalten dieses Codes ist abhängig von der Anwesenheit von -D_REENTRANT
.
solaris$ cc -E test.c | grep return
return errno;
solaris$ cc -D_REENTRANT -E test.c | grep return
return (* (___errno ()));
mit der letzteren Version threadsicher sein. Wenn wir den gleichen Code auf Linux kompilieren, bekommen wir das gleiche Verhalten unabhängig von -D_REENTRANT
linux$ gcc -E test.c | grep return
return (*__errno_location());
linux$ gcc -D_REENTRANT -E test.c | grep return
return (*__errno_location());
Solaris' cc
hat die Option -mt
, die -D_REENTRANT
impliziert, ebenso wie gcc
‚s -pthread
. Bei einer Bibliothek scheint die Angabe dieser Multi-Thread-Optionen jedoch schlecht, da sie eine unnötige Abhängigkeit von der Laufzeit des Threads darstellt. Wenn die Bibliothek jedoch threadsicher (einschließlich Fehlernummern) sein muss, wird die threadsichere Semantik sowohl zur Kompilierungszeit der Bibliothek als auch zum Ableiten des Codes benötigt. Unter Linux ist das einfach, weil errno immer Thread-lokal ist, aber das ist auf anderen Systemen nicht garantiert, wie gerade gezeigt wurde.
Das führt zu der Frage: Wie wird eine threadsichere Bibliothek ordnungsgemäß kompiliert und mit Kopfzeilen verteilt? Eine Option wäre #define _REENTRANT
im Hauptheader, aber dies würde Probleme verursachen, wenn #include <errno.h>
vor der Bibliothek Header-Aufnahme auftritt. Eine andere Option besteht darin, die Bibliothek mit -D_REENTRANT
zu kompilieren und den Hauptkopf #error
zu haben, wenn _REENTRANT
nicht definiert ist.
Was ist der richtige/beste Weg, um eine thread-sichere Bibliothek zu erstellen und sicherzustellen, dass sie korrekt mit dem Code, mit dem sie verknüpft ist, zusammenarbeitet?
'cc -D_POSIX_C_SOURCE = 200112L -E test.c | grep return -> return (* (___errno())); ' Tatsächlich funktioniert das wie erwartet; Empfiehlst du auch, dies in der Kopfzeile der POSIX-kompatiblen Bibliothek zu definieren? –
@AlexanderChernyakhovsky: Nein, es muss nie in einer Header-Datei definiert werden. Es sollte immer am Anfang der Quelldateien definiert werden. Nur so kann sichergestellt werden, dass es vor dem Einfügen von Kopfzeilen definiert ist. Sie können es auch wie in Ihrem Beispiel in der Befehlszeile definieren. Das ist akzeptabel. Ich bevorzuge es in der Quelldatei zu sehen, aber das ist teilweise nur eine Frage des Geschmacks. –
Interessant. Es klingt, als würdest du dafür plädieren, immer noch nach einem "# define" in meinem Bibliothekskopf zu suchen, weil ich immer noch nicht möchte, dass ein Endentwickler das falsche errno bekommt. –