Является ли malloc потокобезопасным?

Это malloc() функция повторного входа?

11 ответов


Я где-то читал, что если вы компилируете с-pthread, malloc становится потокобезопасным. Я уверен, что его реализация зависит, хотя, поскольку malloc-это ANSI C, а потоки-нет.

Если мы говорим gcc:

скомпилировать и связать с-pthread и malloc() будет потокобезопасным, на x86 и Для amd64.

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

другое мнение, более проницательные

{malloc, calloc, realloc, бесплатно, posix_memalign} из glibc-2.2+ являются thread safe

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


вопрос: "является реентерабельным Танос"?
Ответ: Нет, это не так. Вот одно из определений того, что делает рутину reentrant.

ни одна из распространенных версий malloc не позволяет повторно ввести его (например, из обработчика сигналов). Обратите внимание, что повторная процедура может не использовать блокировки, и почти все существующие версии malloc используют блокировки (что делает их потокобезопасными) или глобальные/статические переменные (что делает их потокобезопасными и non-reentrant).

все ответы до сих пор ответ " является ли malloc потокобезопасным?- это совершенно другой вопрос. К это вопрос-ответ зависит в вашей библиотеке времени выполнения и, возможно, на флагах компилятора, которые вы используете. В любом современном UNIX вы получите потокобезопасный malloc по умолчанию. В Windows, используйте /MT, /MTd, /MD или /MDd флаги для получения потокобезопасные библиотеки.


вот выдержка из функции malloc.c из glibc:

Thread-safety: thread-safe, если не определен NO_THREADS

предполагая, что NO_THREADS не определен по умолчанию, malloc является потокобезопасным, по крайней мере, в linux.


Это довольно старый вопрос, и я хочу принести свежесть в соответствии с текущим положением вещей.

Да, в настоящее время malloc() является потокобезопасным.

С справочное руководство библиотеки GNU C of glibc-2.20 [released 2014-09-07]:

void * malloc (size_t size)

предварительный: MT-Safe | ...

... 1.2.2.1 концепции безопасности POSIX:

... Функции MT-Safe или Thread-Safe безопасны для вызова в присутствии других нити. МТ, в МТ-сейфе, стоит для Мулти потока.

быть MT-Safe не означает, что функция атомарна и не использует любой из механизмов синхронизации памяти POSIX предоставляет пользователям. Возможно даже, что вызов функций Mt-Safe в последовательности не выход Mt-безопасная комбинация. Например, наличие вызова потока две функции Mt-Safe одна за другой не гарантируют поведение, эквивалентное атомарному выполнению комбинации обоих функции, поскольку параллельные вызовы в других потоках могут вмешиваться в разрушительный способ.

оптимизация всей программы, которая может встроить функции в библиотеку интерфейсы могут подвергать небезопасному переупорядочению и таким образом выполнять встраивание через интерфейс библиотеки GNU C не рекомендуется. Документально Mt-состояние безопасности не гарантируется underwhole-оптимизация программы. Однако функции, определенные в заголовках, видимых пользователю, должны быть безопасный для встраивания.


да, под POSIX.1-2008 malloc является потокобезопасным.

2.9.1 Потокобезопасности

все функции, определенные этим томом POSIX.1-2008 должен быть потокобезопасным, за исключением того, что после functions1 не должны быть потокобезопасными.

[ список функций, которые не содержат malloc ]


Если вы работаете с GLIBC, ответ: Да, но.

в частности, да, но, пожалуйста, имейте в виду, что в то время как malloc и free являются потокобезопасными,функции отладки не.

в частности, чрезвычайно полезные функции mtrace(), mcheck () и mprobe ()не являются потокобезопасными. В одном из самых коротких и прямых ответов, которые вы когда-либо видели в проекте GNU, это объясняется здесь:

https://sourceware.org/bugzilla/show_bug.cgi?id=9939

вам нужно будет рассмотреть альтернативные методы, такие как ElectricFence, valgrind, dmalloc и т. д.

Итак, если вы имеете в виду "являются ли функции malloc() и free() threadsafe", ответ да. Но если вы имеете в виду, "весь аналог люкс threadsafe", ответ нет.


Это зависит от того, какую реализацию библиотеки времени выполнения C вы используете. Если вы используете MSVC, например, есть параметр компилятора, который позволяет указать, какую версию библиотеки вы хотите построить (т. е. библиотеку времени выполнения, которая поддерживает многопоточность, будучи протекторно-безопасной или нет).


нет, это не является потокобезопасным. На самом деле может быть malloc_lock() и malloc_unlock() функция доступна в вашей библиотеке C. Я знаю, что они существуют для библиотеки Newlib. Мне пришлось использовать это для реализации мьютекса для моего процессора, который многопоточен в аппаратном обеспечении.


malloc и free не реентерабельны, потому что они используют статическую структуру данных, которая записывает то, что блоки памяти бесплатно. В результате, никаких библиотечных функций, выделить или освободить память реентерабельны.



короткий ответ: да, начиная с C11, который является первой версией стандарта C, который включает в себя концепцию потоков,malloc и друзья должны быть потокобезопасными. Многие операционные системы, которые включали как потоки, так и среду выполнения C, сделали эту гарантию задолго до стандарта C, но я не готов поклясться все. Однако,malloc и друзья не обязаны быть реентерабельным.

это означает, что безопасно звонить malloc и free из нескольких потоков одновременно и не беспокоиться о блокировке, пока вы не нарушаете ни одно из других правил выделения памяти (например, вызов free один и только один раз на каждом указателе, возвращаемом malloc). Но это не безопасно вызывать эти функции из обработчика сигнала, который мог прервать вызов malloc или free в потоке, обрабатывающем сигнал. Иногда, используя функции за пределами ISO C, вы можете гарантировать, что обработка потока сигнал не прерывал вызова malloc или free, например,sigprocmask и sigpause, но стараюсь не делать этого, если у вас нет другого выбора, потому что это трудно сделать правильно.


длинный ответ с цитатами: стандарт C добавил концепцию потоков в пересмотр 2011 (ссылка на документ N1570, который является наиболее близким приближением к официальному тексту стандарта 2011 года, который является общедоступным бесплатно). В этой редакции, пункт 5 раздела 7.1.4 гласит:

если явно не указано иное в последующих подробных описаниях, библиотечные функции должны предотвращать гонки данных следующим образом: библиотечная функция не должна прямо или косвенно обращаться к объектам, доступным потоками, отличными от текущего потока, если только к объектам не обращаются прямо или косвенно через аргументы функции. Библиотечная функция не должна прямо или косвенно изменять доступные объекты потоками, отличными от текущего потока, если объекты не доступны прямо или косвенно через аргументы функции non-const. Реализации могут совместно использовать свои внутренние объекты между потоками, если объекты не видны пользователям и защищены от гонки данных.

[сноска: это означает, например, что реализация не может использовать статический объект для внутренних целей без синхронизации, поскольку это может привести к гонке данных даже в программы, которые явно не разделяют объекты между потоками. Аналогично реализации memcpy не разрешается копировать байты за пределы указанной длины целевого объекта, а затем восстановить исходные значения, поскольку это может привести к гонке данных, если программа разделила эти байты между потоками.]

как я понимаю, это многословный способ сказать, что библиотечные функции, определенные стандартом C, должны быть потокобезопасными (в обычном sense: вы можете вызывать их из нескольких потоков одновременно, не блокируя себя, пока они не сталкиваются с данными, переданными в качестве аргументов), если документация для конкретной функции конкретно не говорит, что это не так.

затем, 7.22.3p2 подтверждает, что malloc, calloc, realloc, aligned_alloc и free, в частности, являются потокобезопасными:

для целей определения существования гонки данных, Память функции распределения ведут себя так, как если бы они обращались только к расположениям памяти, доступным через их аргументы, а не к другому статическому хранилищу длительности. Однако эти функции могут заметно изменять хранилище, которое они выделяют или освобождают. Вызов free или realloc, который освобождает область P памяти, синхронизируется с любым вызовом выделения, который выделяет всю или часть области p. Эта синхронизация происходит после любого доступа p функцией освобождения и перед любым таким доступом выделяя функции.

сравните то, что он говорит о strtok, который не является и никогда не был потокобезопасным, в 7.24.5.8p6:

функция strtok не требуется, чтобы избежать "гонки данных" с другими вызовами функция strtok.

[сноска: вместо этого можно использовать функцию strtok_s, чтобы избежать гонки данных.]

(комментарий к сноске: не использовать strtok_s используйте strsep.)

старые версии стандарта C ничего не говорили о безопасности потоков. Однако они ... --15-->сделал сказать что-то о реентерабельности, потому что сигналы всегда были частью стандарта C. И вот что они сказали, возвращаясь к первоначальному 1989 стандарт ANSI C (этот документ имеет почти идентичную формулировку, но очень отличную нумерацию разделов от стандарта ISO C, который вышел в следующем году):

если сигнал [a] возникает иначе, чем в результате вызова прерывания или функция raise, поведение не определено, если обработчик сигнала вызывает любую функцию в стандартной библиотеке, кроме signal сама функция или относится к любому объекту со статической длительностью хранения кроме присвоения значения статической переменной длительности хранения типа volatile sig_atomic_t . Кроме того, если такой призыв функция сигнала приводит к возвращению sig_err, значение errno сомнительный.

который является многословным способом сказать, что функции библиотеки C являются не должна быть реентерабельным, как правило. Очень похожая формулировка все еще появляется в C11,7.14.1.1p5:

если сигнал [a] возникает иначе, чем в результате вызова функции abort или raise, поведение не определено, если обработчик сигнала ссылается на любой объект со статической или потоковой длительностью хранения, который не является свободным от блокировки атомарный объект, отличный от назначения значения объекту, объявленному как volatile sig_atomic_t, или обработчик сигнала вызывает любую функцию в стандартной библиотеке, кроме функции abort, функции _Exit, функции quick_exit или функции сигнала с первым аргументом, равным номеру сигнала, соответствующему сигналу, который вызвал вызов обработчика. Кроме того, если такой вызов функции сигнала приводит к возвращению sig_err, значение errno равно сомнительный.

[сноска: если какой-либо сигнал генерируется асинхронным обработчиком сигнала, поведение не определено.]

POSIX требует гораздо дольше, но все же короткий по сравнению с общим размером библиотеки C, список функций, которые можно безопасно вызывать из "асинхронного обработчика сигналов", а также более подробно определяет обстоятельства, при которых сигнал может " произойти иначе, чем в результате вызова прерывания или вызова функция."Если вы делаете что-то нетривиальное с сигналами, вы, вероятно, пишете код, предназначенный для запуска на ОС с характером Unix (в отличие от Windows, MVS или чего-то встроенного, что, вероятно, не имеет полной размещенной реализации C в первую очередь), и вы должны ознакомиться с требованиями POSIX для них, а также требованиями ISO C.