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

malloc() функция malloc() ?

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

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

Компиляция и связь с -pthread и malloc () будут streamобезопасными, на x86 и AMD64.

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

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

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

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

Вопрос: «malloc reentrant»?
Ответ: нет, это не так. Вот одно определение того, что делает обычным реентерабельным .

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

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

Вот выдержка из malloc.c glibc:

Защита резьбы: без резьбы, если не определено NO_THREADS

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

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

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

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

void * malloc (size_t size)

Предварительно: MT-Safe | …

… 1.2.2.1 Концепции безопасности POSIX:

… Функции MT-Safe или Thread-Safe безопасны для вызова в присутствии других streamов. MT, в MT-Safe, означает Multi Thread.

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

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

Да, в POSIX.1-2008 malloc streamобезопасен.

2.9.1 Защита резьбы

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

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

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

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

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

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

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

Итак, если вы имеете в виду, «это функции malloc () и free () threadsafe», то да. Но если вы имеете в виду, «это весь malloc / free suite threadsafe», ответ НЕТ.

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Запись на указатель вне границ после malloc (), не вызывающая ошибки
  • Многопоточные блокировки памяти для C / C ++
  • Что произойдет, если я попытаюсь получить доступ к памяти за пределами области malloc ()?
  • Как использовать строку C ++ в структуре, когда malloc () - с той же структурой?
  • Почему это намеренно неправильное использование strcpy не терпит неудачу?
  • Как правильно настроить, получить доступ и получить multidimensional array в C?
  • Объясните эту реализацию malloc из книги K & R
  • Поведение malloc с удалением в C ++
  • новички вопросы о malloc и sizeof
  • free char *: недопустимый следующий размер (быстрый)
  • динамически распределенная память после завершения программы
  • Давайте будем гением компьютера.