2016-12-21 2 views
3

Diese answer vorschlagen -pthread ist -lpthread wegen vordefinierten Makros vorzuziehen.-pthread, -lpthread und minimale dynamische Linktime-Abhängigkeiten

Empirisch -pthread gibt mir nur ein zusätzliches Makro: #define _REENTRANT 1 und es scheint auch libpthread.so.0 als dynamisches linktime Abhängigkeit zu zwingen. Wenn ich mit -lpthread kompiliere, wird diese Abhängigkeit nur hinzugefügt, wenn ich tatsächlich eine der pthread Funktionen aufrufen.

Dies ist für mich am besten, weil ich dann Multithread-Programme in meinen Build-Skripten nicht anders behandeln müsste.

Also meine Frage ist, was gibt es sonst noch zu -pthread vs -lpthread und ist es möglich zu verwenden -pthread, ohne diese dynamische Linktime-Abhängigkeit zu erzwingen?

Demonstration:

$ echo 'int main(){ return 0; }' | c gcc -include pthread.h -x c - -lpthread && ldd a.out | grep pthread 
$ echo 'int main(){ return pthread_self(); }' | c gcc -include pthread.h -x c - -lpthread && ldd a.out | grep pthread 
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000003000c00000) 
$ echo 'int main(){ return 0; }' | c gcc -include pthread.h -x c - -pthread && ldd a.out | grep pthread 
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000003000c00000) 
+2

Warum würden Sie '-pthread' (oder' -lpthread') für ein Programm verwenden, das pthreads nicht verwendet? Und wenn Ihr Programm tatsächlich Pthreads verwendet, warum gibt es dann ein Problem? –

+0

Nach meinem Verständnis ist der einzige Grund, warum Sie das wollen, ein universeller Build-Befehl *, was nie eine gute Idee ist. Ich meine, es ist entweder Ihre ausführbare Datei ist Multi-Threading oder nicht. Sie sollten sich nicht auf die intelligente Verbindung von gcc verlassen können. –

+0

@JohnBollinger Generisches Projekt erstellt. – PSkocik

Antwort

7

Die Idee, dass Sie einige anderthalb Jahrzehnten spezielle Option des GCC -pthread statt -lpthread ist nicht aktuell wahrscheinlich verwenden sollten (in Bezug auf glibc, das ist). Im modernen glibc ist die Umstellung auf Threading völlig dynamisch, je nachdem, ob die Pthreads-Bibliothek verknüpft ist oder nicht. Nichts in den Glibc-Headern ändert sein Verhalten basierend darauf, ob _REENTRANT definiert ist. Als Beispiel für die dynamische Umschaltung betrachten Sie FILE * Streams. Bestimmte Vorgänge an Streams sind gesperrt, wie putc. Ob Sie ein Singlethread-Programm kompilieren oder nicht, es ruft die gleiche putc-Funktion auf; Es wird nicht vom Präprozessor zu einem "Pthread-aware" putc umgeleitet. Was passiert, ist, dass Do-Nothing-Stub-Funktionen verwendet werden, um die Bewegungen des Verriegelns und Entsperrens zu durchlaufen. Diese Funktionen erhalten, um echte außer Kraft gesetzt, wenn die Threading-Bibliothek in verknüpft ist.



Ich habe gerade eine kursorisches grep durch den Dateibaum einer glibc-Installation enthalten. In features.h, _REENTRANT wird __USE_REENTRANT definiert. Im Gegenzug hängt genau eine Sache davon ab, ob __USE_REENTRANT vorhanden ist, hat aber eine parallele Bedingung, die es auch ermöglicht. Das heißt, in <unistd.h> gibt es diese:

#if defined __USE_REENTRANT || defined __USE_POSIX199506 
/* Return at most NAME_LEN characters of the login name of the user in NAME. 
    If it cannot be determined or some other error occurred, return the error 
    code. Otherwise return 0. 

    This function is a possible cancellation point and therefore not 
    marked with __THROW. */ 
extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1)); 
#endif 

Das sieht fragwürdig und ist veraltet; Ich kann es nicht im Masterzweig des glibc git repo finden.

Und, oh schauen, nur bloße Tage (6. Dezember) ein zu diesem Thema gemacht wurde commit:

https://sourceware.org/git/?p=glibc.git;a=commit;h=c03073774f915fe7841c2b551fe304544143470f

Make _REENTRANT and _THREAD_SAFE aliases for _POSIX_C_SOURCE=199506L. 

For many years, the only effect of these macros has been to make 
unistd.h declare getlogin_r. _POSIX_C_SOURCE >= 199506L also causes 
this function to be declared. However, people who don't carefully 
read all the headers might be confused into thinking they need to 
define _REENTRANT for any threaded code (as was indeed the case a long 
time ago). 

Zu den Änderungen:

--- a/posix/unistd.h 
+++ b/posix/unistd.h 
@@ -849,7 +849,7 @@ extern int tcsetpgrp (int __fd, __pid_t __pgrp_id) __THROW; 
    This function is a possible cancellation point and therefore not 
    marked with __THROW. */ 
extern char *getlogin (void); 
-#if defined __USE_REENTRANT || defined __USE_POSIX199506 
+#ifdef __USE_POSIX199506 
/* Return at most NAME_LEN characters of the login name of the user in NAME. 
    If it cannot be determined or some other error occurred, return the error 
    code. Otherwise return 0. 

Sehen Sie? :)

+2

"Die Idee, dass Sie die spezielle Option von GCC-pthread anstelle von -lpthread verwenden sollten, ist wahrscheinlich um eineinhalb Jahrzehnte veraltet (in Bezug auf glibc, das ist)." - Das ist richtig, aber * nur * gilt für glibc. Wenn du für andere Plattformen baust, könntest du leicht in Schwierigkeiten geraten, indem du "-pthread" verwendest. Daher ist es vorzuziehen, '-pthread' anstelle von' -lpthread' zu verwenden, da ersteres * immer * korrekt ist und das Letzteres ist nicht unbedingt. –

3

die andere Antwort erklärt, dass -pthread (sowohl kompilieren und Link-Zeit) ist funktionell äquivalent zu -lpthread (zur Verknüpfungszeit nur) , wenn die C-Bibliothek Die GNU C-Bibliothek ist. Aber das ist nicht die einzige C-Bibliothek der Welt.

Ich weiß nicht, ob irgendeine die aktuellen Generation von POSIX-kompatibelen Betriebssysteme etwas benötigen mehr als -lpthread zur Verbindungszeit für eine Gewinde Anwendung, aber wenn Sie -pthread bei Verwendung sowohl kompilieren und verknüpfen Zeit, werden Sie bei Das Leben für die Leute, die versuchen, das alte Eisen am Laufen zu halten, wird dadurch zumindest erleichtert.

Having said that, altes Eisen wird auch glücklicher sein, wenn Sie nicht Gebrauch machen -pthread (oder -lpthread) auf Programme, die Fäden nicht verwenden müssen. "Generic Project Builds" sind keine gute Idee.

Das Problem der gemeinsamen Bibliotheken, die eingezogen werden, wenn sie nicht sein müssen, wird am besten durch -Wl,--as-needed (mit GNU-kompatiblen Linkern) gelöst. Dies ist standardmäßig nur aus Gründen der Abwärtskompatibilität aktiviert.

Verwandte Themen