it-swarm.com.de

Ist malloc threadsicher?

Ist die Funktion malloc() erneut eintritt?

65
Alphaneo

Ich habe irgendwo gelesen, dass, wenn Sie mit -pthread kompilieren, malloc Thread-sicher wird. Ich bin mir ziemlich sicher, dass die Implementierung davon abhängt, da malloc ANSI C ist und Threads nicht.

Wenn wir über gcc sprechen:

Kompilieren und verknüpfen Sie mit -pthread und malloc () wird auf x86 .__ fadensicher. und AMD64.

http://groups.google.com/group/comp.lang.c.moderated/browse_thread/thread/2431a99b9bdcef11/ea800579e40f7fa4

Eine andere Meinung, aufschlussreicher

{malloc, calloc, realloc, kostenlos, posix_memalign} von glibc-2.2 + sind fadensicher

http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2005-07/0323.html

39
Tom

Frage: "ist Malloc wiedereintrittsfähig"?
Antwort: nein, ist es nicht. Hier ist eine Definition dessen, was eine Routine wiedereintrittsfähig macht.

In keiner der gängigen Versionen von malloc können Sie sie erneut eingeben (z. B. von einem Signalhandler). Beachten Sie, dass eine Wiedereintrittsroutine möglicherweise keine Sperren verwendet, und fast alle vorhandenen Malloc-Versionen verwenden Sperren (was sie Thread-sicher macht) oder globale/statische Variablen (wodurch sie Thread-unsicher und nicht wiederkehrend sind) .

Alle Antworten, die bisher beantwortet wurden, lauten "ist Malloc-Thread-sicher?", Was eine völlig andere Frage ist. Auf die Frage that lautet die Antwort es hängt von Ihrer Laufzeitbibliothek und möglicherweise von den verwendeten Compiler-Flags ab. Bei jedem modernen UNIX erhalten Sie standardmäßig ein threadsicheres Malloc. Verwenden Sie unter Windows die Codes /MT, /MTd, /MD oder /MDd, um die Thread-sichere Laufzeitbibliothek abzurufen.

93

Das ist eine ziemlich alte Frage und ich möchte Frische nach dem aktuellen Stand der Dinge bringen.

Ja, derzeit ist malloc() thread-sicher.

Aus dem GNU C Library Reference Manual von glibc-2.20 [released 2014-09-07]:

void * malloc (size_t size)

Vorbemerkung: MT-Safe | ...

... 1.2.2.1 POSIX-Sicherheitskonzepte:

... MT-Safe- oder Thread-Safe-Funktionen können sicher aufgerufen werden, wenn andere Threads vorhanden sind. MT steht in MT-Safe für Multi Thread.

MT-Safe 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 der Aufruf von MT-Safe-Funktionen nacheinander keine MT-Safe-Kombination ergibt. Wenn beispielsweise ein Thread zwei MT-Safe-Funktionen direkt nacheinander aufruft, ist dies keine Garantie für ein Verhalten, das der atomaren Ausführung einer Kombination beider Funktionen entspricht, da gleichzeitige Aufrufe in anderen Threads auf destruktive Weise stören können.

Optimierungen des gesamten Programms, die Funktionen über Bibliotheksschnittstellen hinweg einbinden könnten, können zu einer unsicheren Neuordnung führen. Daher wird eine Inlinierung über die GNU C-Bibliotheksschnittstelle nicht empfohlen. Programmoptimierung In benutzerdefinierten Kopfzeilen definierte Funktionen sind jedoch für das Inlining sicher.

9
likern

Hier ist ein Auszug aus malloc.c von glibc:

Thread-Sicherheit: Thread-sicher, sofern nicht NO_THREADS definiert ist

wenn NO_THREADS nicht standardmäßig definiert ist, ist malloc zumindest unter Linux threadsicher.

9
shahkhas

Ja, unter POSIX.1-2008malloc ist threadsicher.

2.9.1 Fadensicherheit

Alle in diesem Volume von POSIX.1-2008 definierten Funktionen müssen Thread-sicher sein, mit der Ausnahme, dass die folgenden Funktionen1 nicht Thread-sicher sein müssen.

[eine Liste von Funktionen, die malloc nicht enthält]

5
Tanz87

Wenn Sie mit GLIBC arbeiten, lautet die Antwort: Ja, aber.

Ja, aber bitte, bitte beachten Sie, dass, während malloc und free threadsicher sind, die Debugging-Funktionen nicht.

Insbesondere die äußerst nützlichen Funktionen mtrace (), mcheck () und mprobe () sind nicht threadsicher. In einer der kürzesten und direktesten Antworten, die Sie jemals aus einem GNU -Projekt sehen 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 () threadsafe", lautet die Antwort ja. Aber wenn Sie meinen, "ist der gesamte Malloc/free suite threadsafe", lautet die Antwort NEIN.

4
breakpoint

Kurze Antwort: Ja, ab C11, der ersten Version des C-Standards, die das Konzept von Threads enthält, müssen malloc und friends thread-sicher sein. Viele Betriebssysteme, die sowohl Threads als auch eine C-Laufzeit enthalten, haben diese Garantie lange vor dem C-Standard übernommen, aber ich bin nicht bereit, auf alle zu schwören. malloc und Freunde mussten jedoch nicht wiedereintreten.

Das heißt, es ist sicher, malloc und free von mehreren Threads gleichzeitig aufzurufen und sich keine Gedanken über das Sperren zu machen, solange Sie keine der anderen Regeln für die Speicherzuweisung (z. B. call) verletzen free einmal und nur einmal für jeden von malloc zurückgegebenen Zeiger. Es ist jedoch nicht sicher, diese Funktionen von einem Signal-Handler aufzurufen, der möglicherweise einen Aufruf von malloc oder free unterbrochen hat. ] im Thread, der das Signal verarbeitet. Wenn Sie Funktionen außerhalb von ISO C verwenden, können Sie manchmal sicherstellen, dass der Thread, der das Signal verarbeitet, den Aufruf von malloc oder free nicht unterbrochen hat, z. mit sigprocmask und sigpause, aber versuchen Sie es nicht, es sei denn, Sie haben keine andere Option, weil es schwierig ist, perfekt richtig zu machen.


Lange Antwort mit Zitaten: Die C-Norm fügte ein Thread-Konzept in die 2011-Revision ein (der Link ist zum Dokument N1570, das dem offiziellen Text der 2011-Norm, der unter der Nummer 0 öffentlich verfügbar ist, am nächsten kommt aufladen). In dieser Überarbeitung lautet Abschnitt 7.1.4, Absatz 5 :

Sofern in den folgenden detaillierten Beschreibungen nicht ausdrücklich anders angegeben, sollen Bibliotheksfunktionen Datenrassen wie folgt verhindern: 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 von anderen Threads als dem aktuellen Thread zugegriffen werden kann, 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 Datenrassen geschützt sind.

[Fußnote: Dies bedeutet zum Beispiel, dass eine Implementierung kein statisches Objekt für interne Zwecke ohne Synchronisation verwenden darf, da dies selbst in Programmen, die Objekte nicht explizit zwischen Threads austauschen, zu einem Datenwettlauf führen kann. In ähnlicher Weise 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 Datenwettlauf führen kann, wenn das Programm diese Bytes zwischen Threads teilt.]

Nach meinem Verständnis ist dies eine langwierige Art zu sagen, dass die vom 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, dass dies nicht der Fall ist.

Dann bestätigt 7.22.3p2 , dass malloc, calloc, realloc, aligned_alloc und insbesondere free thread-sicher sind:

Um die Existenz eines Datenrennens zu bestimmen, verhalten sich die Speicherzuweisungsfunktionen so, als hätten sie nur auf Speicherstellen zugegriffen, auf die über ihre Argumente zugegriffen werden kann, und nicht auf andere statische Speicherdauern. Diese Funktionen können jedoch den von ihnen zugewiesenen oder freigegebenen Speicher sichtbar verändern. Ein Aufruf zum Freigeben oder Neuzuteilen, der eine Region p des Speichers freigibt, wird mit jedem Zuweisungsaufruf synchronisiert, der die gesamte Region p oder einen Teil davon zuweist. Diese Synchronisation erfolgt nach jedem Zugriff von p durch die Aufhebungsfunktion und vor jedem derartigen Zugriff durch die Zuordnungsfunktion.

Vergleichen Sie, was in 7.24.5.8p6 über strtok steht, das nicht thread-sicher ist und noch nie war:

Die Funktion strtok ist nicht erforderlich, um Datenrennen mit anderen Aufrufen der Funktion strtok zu vermeiden.

[Fußnote: Die Funktion strtok_s kann stattdessen verwendet werden, um Datenrennen zu vermeiden.]

(Kommentar zur Fußnote: benutze nicht strtok_s, verwende strsep.)

Ältere Versionen des C-Standards sagten überhaupt nichts über die Gewindesicherheit aus. Sie haben jedoch etwas über Wiedereintritt gesagt , da Signale immer Teil des C-Standards waren. Und dies ist, was sie sagten und zurückgingen auf das Original 1989 ANSI C-Standard (dieses Dokument hat einen nahezu identischen Wortlaut, aber eine sehr unterschiedliche Abschnittsnummerierung als der ISO C-Standard, der im folgenden Jahr herauskam ):

Wenn das Signal [a] nicht als Ergebnis des Aufrufs der Abbruch- oder Erhöhungsfunktion auftritt, ist das Verhalten undefiniert, wenn der Signalhandler eine andere Funktion in der Standardbibliothek aufruft als die Signalfunktion selbst oder auf ein Objekt mit einer anderen statischen Speicherdauer verweist als durch Zuweisen eines Werts zu einer statischen Speicherdauer-Variablen des Typs volatile sig_atomic_t. Wenn ein solcher Aufruf der Signalfunktion zu einer SIG_ERR-Rückkehr führt, ist der Wert von errno unbestimmt.

Dies ist eine langatmige Art zu sagen, dass C-Bibliotheksfunktionen in der Regel nicht wiedereintrittsfähig sein müssen. Ein sehr ähnlicher Wortlaut erscheint noch in C11, 7.14.1.1p5 :

Wenn das Signal [a] nicht als Ergebnis des Aufrufs der Abbruch- oder Erhöhungsfunktion auftritt, ist das Verhalten nicht definiert, 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 Objekt, das als flüchtig sig_atomic_t deklariert wurde, oder der Signalhandler rufen eine beliebige Funktion in der Standardbibliothek auf, die nicht die Abbruchfunktion, die Funktion _Exit, die Funktion quick_exit oder die Signalfunktion ist, deren erstes Argument der Signalnummer entspricht das Signal, das den Aufruf des Handlers verursacht hat. Wenn ein solcher Aufruf der Signalfunktion zu einer SIG_ERR-Rückkehr führt, ist der Wert von errno unbestimmt.

[Fußnote: Wenn ein Signal von einem asynchronen Signalhandler generiert wird, ist das Verhalten undefiniert.]

POSIX benötigt ein viel länger, aber immer noch kurz im Vergleich zur Gesamtgröße der C-Bibliothek , eine Liste von Funktionen, die von einem "asynchronen Signal-Handler" sicher aufgerufen werden können, und definiert außerdem die Umstände unter welches ein Signal "anders als als das Ergebnis des Aufrufs der Abbruch- oder Erhöhungsfunktion auftreten kann". 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 Sie sollten sich mit den POSIX-Anforderungen und den ISO C-Anforderungen vertraut machen.

2
zwol

Nein, es ist nicht Thread-sicher. In Ihrer C-Bibliothek ist möglicherweise 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 Hardware Multithreading ist.

1
sybreon

malloc und free sind nicht wiedereintrittsfähig, da sie eine statische Datenstruktur verwenden, die aufzeichnet, welche Speicherblöcke frei sind. Folglich sind keine Bibliotheksfunktionen, die Speicher zuweisen oder freigeben, wiedereintrittsfähig.

1
user3379688

Es hängt davon ab, welche Implementierung der C-Laufzeitbibliothek Sie verwenden. Wenn Sie beispielsweise MSVC verwenden, gibt es eine Compiler-Option, mit der Sie angeben können, mit welcher Version der Bibliothek Sie erstellen möchten (z. B. eine Laufzeitbibliothek, die Multithreading unterstützt, weil sie tread-safe ist oder nicht).

1
ChrisW
0
Paul Sonier