Ist malloc Thread-sicher?

Lesezeit: 10 Minuten

Benutzeravatar von Alphaneo
Alphaneo

Ist der malloc() Funktion wiedereintretend?

  • verwandt: stackoverflow.com/questions/147298/…

    – Lothar

    13. Mai 2009 um 2:20 Uhr

  • Ihr Titel und Text fragen nach zwei verschiedenen Dingen. Wiedereintretend bedeutet normalerweise “kann sicher in einem Signalhandler verwendet werden”, während Thread-sicher normalerweise “kann sicher in Threads verwendet werden” bedeutet. Es ist einfacher, threadsicher zu sein als reentrant.

    – David Thornley

    20. September 2010 um 15:11 Uhr

Benutzeravatar des beschäftigten Russen
Angestellter Russe

Frage: “ist malloc reentrant”?
Antwort: nein, ist es nicht. Hier ist eine Definition dessen, was eine Routine ausmacht wiedereintretend.

Keine der gängigen malloc-Versionen erlaubt Ihnen, es erneut einzugeben (zB von einem Signal-Handler). Beachten Sie, dass eine ablaufinvariante Routine möglicherweise keine Sperren verwendet, und fast alle existierenden Malloc-Versionen verwenden Sperren (was sie Thread-sicher macht) oder globale/statische Variablen (was sie Thread-unsicher macht). und nicht wiedereintretend).

Alle bisherigen Antworten beantworten “ist malloc Thread-sicher?”, was eine ganz andere Frage ist. Zu das Frage ist die Antwort es hängt davon ab, ob in Ihrer Laufzeitbibliothek und möglicherweise in den von Ihnen verwendeten Compiler-Flags. Auf jedem modernen UNIX erhalten Sie standardmäßig ein Thread-sicheres Malloc. Verwenden Sie unter Windows /MT, /MTd, /MD oder /MDd Flags, um eine Thread-sichere Laufzeitbibliothek zu erhalten.

  • Wiedereintrittsroutinen können Sperren verwenden, solange die Sperre wiedereintrittsfähig ist; Dies erfordert, dass die Sperre ungefähr einem rekursiven oder fehlerüberprüfenden Mutex entspricht, jedoch mit der zusätzlichen Bedingung, dass die einzelne atomare Operation, die die Sperre übernimmt, dazu führen muss, dass sich die Sperrstruktur für eine neu gehaltene Sperre mit einem einzigen in einem konsistenten Zustand befindet Hinweis. Natürlich müssen Sie sich dann auch mit dem Fall befassen, in dem der durch die Sperre geschützte Zustand teilweise durch den unterbrochenen Code im selben Thread geändert wurde, aber dennoch können reentrant Sperren ein Baustein sein, um damit umzugehen …

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    21. Oktober 2011 um 11:53 Uhr

  • Ich glaube, /MT /MTd /MD usw. bedeutet nur, dass entweder Release/Debug/Dynamische oder statische CRT-Version verwendet wird, nicht dass Malloc Thread-sicher ist oder nicht (es ruft tatsächlich HeapAlloc auf, das ein optionales Flag ohne Serialisierung hat).

    – paulm

    1. April 2016 um 13:40 Uhr

Toms Benutzeravatar
Tom

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

Wenn wir über gcc sprechen:

Das Kompilieren und Linken mit -pthread und malloc() ist Thread-sicher, auf x86 und AMD64.

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

Eine andere Meinung, aufschlussreicher

{malloc, calloc, realloc, free, posix_memalign} von glibc-2.2+ sind Thread-sicher

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

  • “Ich habe irgendwo gelesen …” ist wirklich nicht die Art von Qualität, die einer akzeptierten Antwort gebührt.. 😉

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    21. Oktober 2011 um 11:51 Uhr

  • Was auch immer er die Verweislinks liefert.

    – Kette ro

    3. Dezember 2014 um 7:02 Uhr

  • Beachten Sie, dass das einfache Hinzufügen -pthreads macht Malloc-Threads nicht automatisch sicher. Wenn Sie malloc in einem Signalhandler aufrufen, kann allerlei verrückter Unsinn passieren.

    – DIMMSumme

    23. April 2016 um 3:47 Uhr

  • malloc wird nicht als sicher erachtet, von einem Signal-Handler aus aufgerufen zu werden; sehr wenig ist. Es kann in einigen Kontexten funktionieren, aber nicht legal oder portabel AFAIK (siehe en.cppreference.com/w/c/program/signal, man7.org/linux/man-pages/man7/signal-safety.7.html)

    – Oliver Seiler

    4. Januar 2018 um 16:37 Uhr

likerns Benutzeravatar
mögen

Das ist eine ziemlich alte Frage, und ich möchte sie nach aktuellem Stand der Dinge auffrischen.

Ja, aktuell malloc() ist Thread-sicher.

Von dem Referenzhandbuch zur GNU C-Bibliothek 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 in Gegenwart anderer Threads sicher aufgerufen werden. MT, in MT-Safe, steht für Multi Thread.

MT-sicher zu sein bedeutet nicht, dass eine Funktion atomar ist oder dass sie einen der Speichersynchronisierungsmechanismen verwendet, die POSIX den 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, garantiert dies kein Verhalten, das der atomaren Ausführung einer Kombination beider Funktionen entspricht, da gleichzeitige Aufrufe in anderen Threads auf destruktive Weise interferieren können.

Optimierungen des gesamten Programms, die Funktionen über Bibliotheksschnittstellen hinweg inlinen könnten, können eine unsichere Neuordnung aufdecken, und daher wird das Durchführen von Inlining über die GNU C Library-Schnittstelle hinweg nicht empfohlen. Der dokumentierte MT-Safety-Status wird nicht unter der gesamten Programmoptimierung garantiert. Funktionen, die in für den Benutzer sichtbaren Headern definiert sind, sind jedoch so konzipiert, dass sie für das Inlining sicher sind.

Ja, unter POSIX.1-2008 malloc ist Thread-sicher.

2.9.1 Thread-Sicherheit

Alle in diesem Band von POSIX.1-2008 definierten Funktionen sollen Thread-sicher sein, außer dass die folgenden Funktionen1 nicht Thread-sicher sein müssen.

[ a list of functions that does not contain malloc ]

Hier ist ein Auszug aus malloc.c von glibc :

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

Unter der Annahme, dass NO_THREADS nicht standardmäßig definiert ist, ist malloc zumindest unter Linux Thread-sicher.

Benutzeravatar von breakpoint
Haltepunkt

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

Insbesondere ja, ABER bitte beachten Sie, dass malloc und free Thread-sicher sind, die Debugging-Funktionen sind es nicht.

Insbesondere die äußerst nützlichen Funktionen mtrace(), mcheck() und mprobe() sind nicht Thread-sicher. In einer der kürzesten und direktesten Antworten, die Sie jemals von 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() threadsicher”, lautet die Antwort ja. Aber wenn du meinst, “ist das ganze malloc/free Suite threadsafe”, lautet die Antwort NEIN.

Benutzeravatar der Community
Gemeinschaft

Kurze Antwort: Ja, ab C11, der ersten Version des C-Standards, die das Konzept von Threads enthält, malloc und Freunde müssen Thread-sicher sein. Viele Betriebssysteme, die sowohl Threads als auch eine C-Laufzeitumgebung enthielten, haben diese Garantie lange vor dem C-Standard gegeben, aber ich bin nicht bereit, darauf zu schwören alle. Jedoch, malloc und Freunde sind und waren nie verpflichtet, reentrant zu sein.

Das heißt, es ist sicher anzurufen malloc und free aus mehreren Threads gleichzeitig und sorgen Sie sich nicht um das Sperren, solange Sie keine der anderen Regeln der Speicherzuweisung verletzen (z. B. call free einmal und nur einmal für jeden von zurückgegebenen Zeiger malloc). Aber es ist nicht sicher, diese Funktionen von einem Signal-Handler aufzurufen, der möglicherweise einen Aufruf unterbrochen hat malloc oder free in dem Thread, der das Signal behandelt. Manchmal können Sie durch die Verwendung von Funktionen jenseits von ISO C garantieren, dass der Thread, der das Signal verarbeitet, einen Aufruf von nicht unterbrochen hat malloc oder freezB mit sigprocmask und sigpauseaber versuchen Sie, dies nicht zu tun, es sei denn, Sie haben keine andere Möglichkeit, da es schwierig ist, es perfekt zu machen.


Lange Antwort mit Zitaten: Der C-Standard fügte ein Konzept von Threads hinzu Überarbeitung 2011 (Der Link führt zum Dokument N1570, das die engste Annäherung an den offiziellen Text des Standards von 2011 darstellt, der kostenlos öffentlich verfügbar ist). In dieser Überarbeitung Ziffer 7.1.4 Absatz 5 Zustände:

Sofern in den folgenden detaillierten Beschreibungen nicht ausdrücklich anders angegeben, sollen Bibliotheksfunktionen Data Races wie folgt verhindern: Eine Bibliotheksfunktion darf nicht direkt oder indirekt auf Objekte zugreifen, auf die andere Threads als der aktuelle Thread zugreifen können, es sei denn, auf die Objekte wird direkt oder indirekt über die Argumente der Funktion zugegriffen . Eine Bibliotheksfunktion darf Objekte, auf die andere Threads als der aktuelle Thread zugreifen können, weder direkt noch indirekt modifizieren, 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 teilen, wenn die Objekte für Benutzer nicht sichtbar und gegen Datenrennen geschützt sind.

[footnote: This means, for example, that an implementation is not permitted to use a static object for internal purposes without synchronization because it could cause a data race even in programs that do not explicitly share objects between threads. Similarly, an implementation of memcpy is not permitted to copy bytes beyond the specified length of the destination object and then restore the original values because it could cause a data race if the program shared those bytes between threads.]

So wie ich es verstehe, ist dies eine langatmige Art zu sagen, dass die vom C-Standard definierten Bibliotheksfunktionen Thread-sicher sein müssen (im üblichen Sinne: Sie können sie von mehreren Threads gleichzeitig aufrufen, ohne selbst zu sperren , solange sie nicht mit den als Argumenten übergebenen Daten kollidieren), es sei denn, die Dokumentation für eine bestimmte Funktion sagt ausdrücklich, dass dies nicht der Fall ist.

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

Zum Zwecke der Bestimmung des Vorhandenseins eines Datenrennens verhalten sich Speicherzuordnungsfunktionen so, als ob sie nur auf Speicherstellen zugreifen würden, auf die durch ihre Argumente zugegriffen werden kann, und nicht auf andere statische Dauerspeicher. Diese Funktionen können jedoch den Speicher, den sie zuweisen oder freigeben, sichtbar modifizieren. Ein Aufruf zum Freigeben oder Neuzuordnen, der einen Speicherbereich p freigibt, wird mit jedem Zuweisungsaufruf synchronisiert, der den gesamten oder einen Teil des Bereichs p zuordnet. Diese Synchronisation erfolgt nach jedem Zugriff auf p durch die Zuordnungsaufhebungsfunktion und vor einem solchen Zugriff durch die Zuordnungsfunktion.

Vergleichen Sie, was es über strtok sagt, das nicht Thread-sicher ist und nie war, in 7.24.5.8p6:

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

[footnote: The strtok_s function can be used instead to avoid data races.]

(Anmerkung zur Fußnote: nicht verwenden strtok_sverwenden strsep.)

Ältere Versionen des C-Standards sagten überhaupt nichts über Thread-Sicherheit aus. Allerdings sie tat etwas über Reentrancy sagen, denn Signale waren schon immer Teil des C-Standards. Und das haben sie gesagt, zurück zum Original 1989 ANSI-C-Standard (Dieses Dokument hat einen nahezu identischen Wortlaut, aber eine sehr unterschiedliche Abschnittsnummerierung von der ISO-C-Norm, die im folgenden Jahr herauskam):

Wenn [a] Signal anders als als Ergebnis des Aufrufs der Abort- oder Raise-Funktion auftritt, ist das Verhalten undefiniert, wenn der Signalhandler eine andere Funktion in der Standardbibliothek als die Signalfunktion selbst aufruft oder auf ein Objekt mit statischer Speicherdauer verweist, außer durch Zuweisung von a value in eine statische Speicherdauervariable vom Typ volatile sig_atomic_t . Wenn außerdem ein solcher Aufruf der Signalfunktion zu einer SIG_ERR-Rückgabe führt, ist der Wert von errno unbestimmt.

Was eine langatmige Art zu sagen ist, dass C-Bibliotheksfunktionen sind nicht grundsätzlich wiedereintrittsfähig sein. Sehr ähnlicher Wortlaut erscheint immer noch in C11, 7.14.1.1p5:

Wenn [a] Signal anders als als Ergebnis des Aufrufs der Abort- oder Raise-Funktion auftritt, ist das Verhalten undefiniert, wenn der Signal-Handler auf ein Objekt mit statischer oder Thread-Speicherdauer verweist, das kein lock-freies atomares Objekt ist, außer durch Zuweisen eines Werts zu an als flüchtiges sig_atomic_t deklariertes Objekt, oder der Signal-Handler ruft eine beliebige Funktion in der Standardbibliothek auf, außer der Abort-Funktion, der _Exit-Funktion, der Quick_exit-Funktion oder der Signal-Funktion, wobei das erste Argument gleich der Signalnummer ist, die dem verursachten Signal entspricht der Aufruf des Handlers. Wenn außerdem ein solcher Aufruf der Signalfunktion zu einer SIG_ERR-Rückgabe führt, ist der Wert von errno unbestimmt.

[footnote: If any signal is generated by an asynchronous signal handler, the behavior is undefined.]

POSIX erfordert a viel länger, aber immer noch kurz im Vergleich zur Gesamtgröße der C-Bibliothek, Liste von Funktionen, die sicher von einem “asynchronen Signalhandler” aufgerufen werden können, und definiert auch detaillierter die Umstände, unter denen ein Signal “anders als als Ergebnis des Aufrufs der Abort- oder Raise-Funktion auftreten kann”. Wenn Sie etwas nicht Triviales mit Signalen machen, schreiben Sie wahrscheinlich Code, der auf einem Betriebssystem mit Unix-Natur 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.

1418330cookie-checkIst malloc Thread-sicher?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy