Ist die malloc()
Funktion wieder verfügbar?
Ist die malloc()
Funktion wieder verfügbar?
Antworten:
Ich habe irgendwo gelesen, dass malloc threadsicher wird, wenn Sie mit -pthread kompilieren. Ich bin mir ziemlich sicher, dass die Implementierung davon abhängt, da malloc ANSI C ist und Threads nicht.
Wenn wir über gcc sprechen:
Das Kompilieren und Verknüpfen mit -pthread und malloc () ist auf x86 und AMD64 threadsicher.
Eine andere Meinung, aufschlussreicher
{malloc, calloc, realloc, free, posix_memalign} von glibc-2.2 + sind threadsicher
http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2005-07/0323.html
-pthreads
den Malloc-Thread nicht automatisch sicher macht. Wenn Sie malloc in einem Signalhandler aufrufen, können alle Arten von verrücktem Unsinn passieren.
Frage: "Ist Malloc wiedereintrittsfähig?"
Antwort: Nein, das ist es nicht. Hier ist eine Definition dessen, was einen routinemäßigen Wiedereintritt ausmacht .
In keiner der gängigen Versionen von malloc können Sie es erneut eingeben (z. B. von einem Signalhandler). Beachten Sie, dass eine Wiedereintrittsroutine möglicherweise keine Sperren verwendet und fast alle existierenden Malloc-Versionen Sperren (wodurch sie threadsicher sind) oder globale / statische Variablen (wodurch sie threadsicher und nicht wiedereintrittsfähig sind) verwenden.
Alle bisherigen Antworten antworten auf "Ist Malloc-Thread-sicher?", Was eine ganz andere Frage ist. Um diese Frage , die Antwort ist es hängt auf Ihrer Laufzeitbibliothek und möglicherweise auf dem Compiler - Flags , die Sie verwenden. Unter jedem modernen UNIX erhalten Sie standardmäßig ein thread-sicheres Malloc. Unter Windows verwenden /MT
, /MTd
, /MD
oder /MDd
Fahnen Thread-sichere Laufzeitbibliothek zu erhalten.
Dies ist eine ziemlich alte Frage, und ich möchte dem aktuellen Stand der Dinge Frische verleihen.
Ja, ist derzeit malloc()
threadsicher.
Aus dem GNU C Library Referenzhandbuch von glibc-2.20 [released 2014-09-07]
:
void * malloc (size_t size)
Vorläufig: MT-Safe | ...
... 1.2.2.1 POSIX-Sicherheitskonzepte:
... MT-Safe- oder Thread-Safe-Funktionen können bei Vorhandensein anderer Threads sicher aufgerufen werden. MT steht in MT-Safe für Multi Thread.
MT-Safe zu sein bedeutet nicht, dass eine Funktion atomar ist oder einen der Speichersynchronisationsmechanismen verwendet, die POSIX Benutzern zur Verfügung stellt. Es ist sogar möglich, dass das Aufrufen von MT-Safe-Funktionen nacheinander keine MT-Safe-Kombination ergibt. Wenn ein Thread beispielsweise zwei MT-Safe-Funktionen direkt nacheinander aufruft, ist kein Verhalten garantiert, das der atomaren Ausführung einer Kombination beider Funktionen entspricht, da gleichzeitige Aufrufe in anderen Threads destruktiv stören können.
Optimierungen für das gesamte Programm, bei denen Funktionen über Bibliotheksschnittstellen hinweg integriert werden können, können zu unsicheren Neuordnungen führen. Daher wird das Inlining über die GNU C-Bibliotheksschnittstelle nicht empfohlen. Der dokumentierte MT-Sicherheitsstatus kann nicht für die Optimierung des gesamten Programms garantiert werden. In benutzerdefinierten Headern definierte Funktionen sind jedoch so konzipiert, dass sie für das Inlining sicher sind.
Ja, unter POSIX.1-2008 malloc
ist threadsicher.
2.9.1 Gewindesicherheit
Alle in diesem Band von POSIX.1-2008 definierten Funktionen müssen threadsicher sein, mit der Ausnahme, dass die folgenden Funktionen1 nicht threadsicher sein müssen.
[eine Liste von Funktionen, die nicht enthält
malloc
]
Wenn Sie mit GLIBC arbeiten, lautet die Antwort: Ja, ABER.
Insbesondere, ja, ABER, bitte, bitte beachten Sie, dass malloc und free zwar threadsicher sind, die Debugging-Funktionen jedoch nicht.
Insbesondere sind die äußerst nützlichen Funktionen mtrace (), mcheck () und mprobe () nicht threadsicher . In einer der kürzesten und direktesten Antworten, die Sie jemals von einem GNU-Projekt erhalten werden, wird dies hier erklärt:
https://sourceware.org/bugzilla/show_bug.cgi?id=9939
Sie müssen alternative Techniken wie ElectricFence, Valgrind, Dmalloc usw. in Betracht ziehen.
Wenn Sie also meinen, "sind die Funktionen malloc () und free () threadsicher", lautet die Antwort "Ja". Aber wenn Sie meinen, "ist die gesamte malloc / free suite threadsicher", lautet die Antwort NEIN.
Kurze Antwort: Ja, ab C11, der ersten Version des C-Standards, die das Konzept von Threads enthält, müssen malloc
Freunde threadsicher sein. Viele Betriebssysteme, die beide Threads und eine C-Laufzeit enthielten, haben diese Garantie lange vor dem C-Standard gegeben, aber ich bin nicht bereit, allen zu schwören . Allerdings malloc
und Freunde sind nicht und nie aufgefordert wurden , einspringende zu sein.
Das heißt, es ist sicher, mehrere Threads gleichzeitig aufzurufen malloc
und zu verwenden, free
ohne sich Gedanken über das Sperren zu machen, solange Sie keine der anderen Regeln für die Speicherzuweisung verletzen (z. B. free
einmal und nur einmal für jeden von zurückgegebenen Zeiger aufrufen malloc
). Es ist jedoch nicht sicher, diese Funktionen von einem Signalhandler aus aufzurufen, der möglicherweise einen Aufruf an malloc
oder free
in dem Thread, der das Signal verarbeitet, unterbrochen hat . Wenn Sie Funktionen verwenden, die über ISO C hinausgehen, können Sie manchmal sicherstellen, dass der Thread, der das Signal verarbeitet, einen Aufruf von malloc
oder free
, z. B. mit sigprocmask
und sigpause
, nicht unterbrochen hat. Versuchen Sie dies jedoch nicht, es sei denn, Sie haben keine andere Option, da es schwierig ist, die richtigen Ergebnisse zu erzielen.
Lange Antwort mit Zitaten: Der C-Standard hat in der Überarbeitung von 2011 ein Thread-Konzept hinzugefügt (Link führt zum Dokument N1570, das dem offiziellen Text des 2011-Standards, der kostenlos öffentlich verfügbar ist, am nächsten kommt). In dieser Überarbeitung heißt es in Abschnitt 7.1.4 Absatz 5 :
Sofern in den folgenden detaillierten Beschreibungen nicht ausdrücklich anders angegeben, verhindern Bibliotheksfunktionen Datenrennen wie folgt: Eine Bibliotheksfunktion darf nicht direkt oder indirekt auf Objekte zugreifen, auf die andere Threads als der aktuelle Thread zugreifen, es sei denn, auf die Objekte wird direkt oder indirekt über die Argumente der Funktion zugegriffen . Eine Bibliotheksfunktion darf keine Objekte direkt oder indirekt ändern, auf die andere Threads als der aktuelle Thread zugreifen können, es sei denn, auf die Objekte wird direkt oder indirekt über die nicht konstanten Argumente der Funktion zugegriffen. Implementierungen können ihre eigenen internen Objekte zwischen Threads gemeinsam nutzen, wenn die Objekte für Benutzer nicht sichtbar und vor Datenrennen geschützt sind.
[Fußnote: Dies bedeutet beispielsweise, dass eine Implementierung ein statisches Objekt ohne Synchronisierung nicht für interne Zwecke verwenden darf, da dies selbst in Programmen, die Objekte nicht explizit zwischen Threads gemeinsam nutzen, zu einem Datenrennen führen kann. Ebenso ist es einer Implementierung von memcpy nicht gestattet, Bytes über die angegebene Länge des Zielobjekts hinaus zu kopieren und dann die ursprünglichen Werte wiederherzustellen, da dies zu einem Datenrennen führen kann, wenn das Programm diese Bytes zwischen Threads teilt.]
Soweit ich weiß, ist dies eine langwierige Art zu sagen, dass die durch den C-Standard definierten Bibliotheksfunktionen threadsicher sein müssen (im üblichen Sinne: Sie können sie von mehreren Threads gleichzeitig aufrufen, ohne sich selbst zu sperren , solange sie nicht mit den als Argumente übergebenen Daten in Konflikt geraten), es sei denn, die Dokumentation für eine bestimmte Funktion besagt ausdrücklich, dass dies nicht der Fall ist.
Dann bestätigt 7.22.3p2 , dass malloc, calloc, realloc, align_alloc und insbesondere free threadsicher sind:
Um die Existenz eines Datenrennens zu bestimmen, verhalten sich Speicherzuweisungsfunktionen so, als hätten sie nur auf Speicherorte zugegriffen, auf die über ihre Argumente zugegriffen werden kann, und nicht auf andere Speicher mit statischer Dauer. Diese Funktionen können jedoch den von ihnen zugewiesenen oder freigegebenen Speicher sichtbar ändern. Ein Aufruf zum Freigeben oder Neuzuweisen, der die Zuweisung einer Region p des Speichers aufhebt, wird mit jedem Zuweisungsaufruf synchronisiert, der die Region p ganz oder teilweise zuweist. Diese Synchronisation erfolgt nach jedem Zugriff von p durch die Freigabefunktion und vor einem solchen Zugriff durch die Zuweisungsfunktion.
Kontrast , was es sagt über strtok, was nicht und nie ist gewesen Thread-sicher, in 7.24.5.8p6 :
Die strtok-Funktion ist nicht erforderlich, um Datenrennen mit anderen Aufrufen der strtok-Funktion zu vermeiden.
[Fußnote: Die Funktion strtok_s kann stattdessen verwendet werden, um Datenrennen zu vermeiden.]
(Kommentar zur Fußnote: nicht verwenden strtok_s
, verwenden strsep
.)
Ältere Versionen des C-Standards sagten überhaupt nichts über die Gewindesicherheit aus. Aber sie tat sagt etwas über reentrancy, weil Signale immer einen Teil des C Standard. Und dies ist, was sie sagten und auf den ursprünglichen ANSI C-Standard von 1989 zurückgingen (dieses Dokument hat einen nahezu identischen Wortlaut, unterscheidet sich jedoch stark von der Abschnittsnummerierung des ISO C-Standards, der im folgenden Jahr herauskam):
Wenn ein [a] -Signal nicht als Ergebnis des Aufrufs der Abbruch- oder Erhöhungsfunktion auftritt, ist das Verhalten undefiniert, wenn der Signalhandler eine andere Funktion in der Standardbibliothek als die Signalfunktion selbst aufruft oder auf ein Objekt mit einer anderen statischen Speicherdauer verweist als durch Zuweisen eines Werts zu einer statischen Speicherdauervariablen vom Typ flüchtig sig_atomic_t. Wenn ein solcher Aufruf der Signalfunktion zu einer SIG_ERR-Rückgabe führt, ist der Wert von errno unbestimmt.
Das ist eine langatmige Art zu sagen , dass C - Bibliotheksfunktionen sind nicht einspringenden als allgemeine Regel sein , erforderlich. Ein sehr ähnlicher Wortlaut erscheint immer noch in C11, 7.14.1.1p5 :
Wenn ein [a] -Signal nicht als Ergebnis des Aufrufs der Abbruch- oder Erhöhungsfunktion auftritt, ist das Verhalten undefiniert, wenn der Signalhandler auf ein Objekt mit statischer oder Thread-Speicherdauer verweist, das kein sperrfreies atomares Objekt ist, außer durch Zuweisen Ein Wert für ein als flüchtig deklariertes Objekt sig_atomic_t oder der Signalhandler ruft eine andere Funktion in der Standardbibliothek als die Abbruchfunktion, die _Exit-Funktion, die quick_exit-Funktion oder die Signalfunktion auf, wobei das erste Argument der entsprechenden Signalnummer entspricht das Signal, das den Aufruf des Handlers verursacht hat. Wenn ein solcher Aufruf der Signalfunktion zu einer SIG_ERR-Rückgabe führt, ist der Wert von errno unbestimmt.
[Fußnote: Wenn ein Signal von einem asynchronen Signalhandler generiert wird, ist das Verhalten undefiniert.]
POSIX erfordert eine viel längere, aber im Vergleich zur Gesamtgröße der C-Bibliothek immer noch kurze Liste von Funktionen, die von einem "asynchronen Signalhandler" sicher aufgerufen werden können, und definiert auch detaillierter die Umstände, unter denen ein Signal "anders auftreten kann" als Ergebnis des Aufrufs der Abbruch- oder Erhöhungsfunktion. " Wenn Sie mit Signalen etwas nicht Triviales tun, schreiben Sie wahrscheinlich Code, der auf einem Betriebssystem mit Unix-Charakter ausgeführt werden soll (im Gegensatz zu Windows, MVS oder etwas Eingebettetem, das wahrscheinlich keine vollständig gehostete Implementierung von C in hat an erster Stelle), und Sie sollten sich mit den POSIX-Anforderungen für sie sowie den ISO C-Anforderungen vertraut machen.
Dies hängt davon ab, welche Implementierung der C-Laufzeitbibliothek Sie verwenden. Wenn Sie beispielsweise MSVC verwenden, gibt es eine Compileroption, mit der Sie angeben können, mit welcher Version der Bibliothek Sie erstellen möchten (dh eine Laufzeitbibliothek, die Multithreading unterstützt, indem sie für das Profil sicher ist oder nicht).
Nein, es ist nicht threadsicher. Möglicherweise ist in Ihrer C-Bibliothek tatsächlich eine malloc_lock()
und- malloc_unlock()
Funktion verfügbar. Ich weiß, dass diese für die Newlib-Bibliothek existieren. Ich musste dies verwenden, um einen Mutex für meinen Prozessor zu implementieren, der in der Hardware über mehrere Threads verfügt.
malloc und free sind nicht wiedereintrittsfähig, da sie eine statische Datenstruktur verwenden, die aufzeichnet, welche Speicherblöcke frei sind. Infolgedessen sind keine Bibliotheksfunktionen, die Speicher zuweisen oder freigeben, wiedereintrittsfähig.
Nein ist es nicht.
Ich schlage vor zu lesen
§31.1 Gewindesicherheit (und Wiedereintritt überarbeitet)
des Buches The Linux Programming Interface erklärt den Unterschied zwischen Thread-Sicherheit und Wiedereintritt sowie malloc
.
Auszug:
Eine Funktion gilt als threadsicher, wenn sie von mehreren Threads gleichzeitig sicher aufgerufen werden kann. Umgekehrt, wenn eine Funktion nicht threadsicher ist, können wir sie nicht von einem Thread aus aufrufen, während sie in einem anderen Thread ausgeführt wird.
....
Diese Funktion zeigt den typischen Grund, warum eine Funktion nicht threadsicher ist: Sie verwendet globale oder statische Variablen, die von allen Threads gemeinsam genutzt werden....
Obwohl die Verwendung kritischer Abschnitte zur Implementierung der Thread-Sicherheit eine erhebliche Verbesserung gegenüber der Verwendung von Mutexen pro Funktion darstellt, ist sie dennoch etwas ineffizient, da das Sperren und Entsperren eines Mutex mit Kosten verbunden ist. Eine Wiedereintrittsfunktion erreicht die Gewindesicherheit ohne die Verwendung von Mutexen. Dies geschieht, indem die Verwendung globaler und statischer Variablen vermieden wird.... Es können
jedoch nicht alle Funktionen wiedereintrittsfähig gemacht werden. Die üblichen Gründe sind folgende:
- Einige Funktionen müssen naturgemäß auf globale Datenstrukturen zugreifen. Die Funktionen in der Malloc-Bibliothek sind ein gutes Beispiel. Diese Funktionen führen eine global verknüpfte Liste freier Blöcke auf dem Heap. Die Funktionen der
malloc
Bibliothek werden durch die Verwendung von Mutexen threadsicher gemacht.....
Auf jeden Fall eine Lektüre wert.
Und um Ihre Frage zu beantworten, malloc
ist threadsicher, aber nicht wiedereintrittsfähig.