Распределение динамической памяти C - C dynamic memory allocation

Распределение динамической памяти C относится к выполнению ручное управление памятью за распределение динамической памяти в Язык программирования C через группу функций в Стандартная библиотека C, а именно маллок, перераспределить, каллок и свободный.[1][2][3]

В C ++ язык программирования включает эти функции; однако операторы новый и Удалить предоставляют аналогичные функции и рекомендуются авторами этого языка.[4] Тем не менее, есть несколько ситуаций, в которых использование новый / удалить неприменимо, например код сборки мусора или код, чувствительный к производительности, а также комбинация маллок и размещение новое может потребоваться вместо вышестоящего новый оператор.

Множество различных реализаций фактического механизма распределения памяти, используемых маллок, доступны. Их производительность зависит как от времени выполнения, так и от требуемой памяти.

Обоснование

В Язык программирования C управляет памятью статически, автоматически, или же динамично. Переменные статической продолжительности выделяются в основной памяти, обычно вместе с исполняемым кодом программы, и сохраняются в течение всего времени существования программы; переменные автоматической продолжительности размещаются на куча и приходят и уходят, когда функции вызываются и возвращаются. Для переменных static-duration и automatic-duration размер выделения должен быть время компиляции константа (кроме случая автоматических массивов переменной длины[5]). Если требуемый размер неизвестен до время выполнения (например, если данные произвольного размера считываются от пользователя или из файла на диске), то использование объектов данных фиксированного размера неадекватно.

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

Этих ограничений можно избежать, используя распределение динамической памяти, в котором память управляется более явно (но более гибко), обычно путем выделения ее из бесплатный магазин (неформально называемая «куча»), область памяти, структурированная для этой цели. В C библиотечная функция маллок используется для выделения блока памяти в куче. Программа обращается к этому блоку памяти через указатель который маллок возвращается. Когда память больше не нужна, указатель передается в свободный который освобождает память, чтобы ее можно было использовать для других целей.

Первоначальное описание C указывало, что каллок и cfree были в стандартной библиотеке, но не маллок. Код для реализации простой модели диспетчера хранилища для Unix был дан с выделить и свободный как функции пользовательского интерфейса, и используя sbrk системный вызов для запроса памяти у операционной системы.[6] Документация Unix 6-го издания дает выделить и свободный как функции распределения памяти низкого уровня.[7] В маллок и свободный подпрограммы в их современном виде полностью описаны в руководстве Unix 7-го издания.[8][9]

Некоторые платформы предоставляют библиотеку или внутренняя функция вызовы, которые позволяют динамическое размещение во время выполнения из стека C, а не из кучи (например, alloca ()[10]). Эта память автоматически освобождается, когда вызывающая функция завершается.

Обзор функций

Функции распределения динамической памяти C определены в stdlib.h заголовок (cstdlib заголовок в C ++).[1]

ФункцияОписание
маллоквыделяет указанное количество байтов
перераспределитьувеличивает или уменьшает размер указанного блока памяти, при необходимости перемещая его
каллоквыделяет указанное количество байтов и инициализирует их нулями
свободныйосвобождает указанный блок памяти обратно в систему

Различия между malloc () и calloc ()

  • malloc () принимает единственный аргумент (количество выделяемой памяти в байтах), а calloc () требуется два аргумента (количество переменных для размещения в памяти и размер одной переменной в байтах).
  • malloc () не инициализирует выделенную память, а calloc () гарантирует, что все байты выделенного блока памяти были инициализированы до 0.
  • В некоторых операционных системах calloc () может быть реализован путем первоначального указания всех страниц виртуальных адресов выделенной памяти на доступную только для чтения страницу со всеми нулями и выделения физических страниц только для чтения и записи, когда виртуальные адреса записываются, метод, называемый копирование при записи.

Пример использования

Создание множество десяти целых чисел с автоматической областью видимости просто в C:

int множество[10];

Однако размер массива фиксируется во время компиляции. Если кто-то желает динамически размещать аналогичный массив, можно использовать следующий код:

int *множество = маллок(10 * размер(int));

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

Потому что маллок не сможет обработать запрос, он может вернуть нулевой указатель и это хорошая практика программирования, чтобы проверить это:

int *множество = маллок(10 * размер(int));если (множество == НОЛЬ) {  fprintf(stderr, "malloc не удалось п");  возвращаться -1;}

Когда программе больше не нужен динамический массив, она должна в конечном итоге вызвать свободный чтобы вернуть занимаемую память в бесплатное хранилище:

свободный(множество);

Память, отложенная маллок не является инициализирован и может содержать хлам: остатки ранее использованных и отброшенных данных. После выделения с маллок, элементы массива неинициализированные переменные. Команда каллок вернет выделение, которое уже было очищено:

int *множество = каллок(10, размер(int));

С помощью realloc мы можем изменить размер памяти, на которую указывает указатель. Например, если у нас есть указатель, действующий как массив размера и мы хотим изменить его на массив размером , мы можем использовать realloc.

int *обр = маллок(2 * размер(int));обр[0] = 1;обр[1] = 2;обр = перераспределить(обр, 3 * размер(int));обр[2] = 3;

Обратите внимание, что следует предполагать, что перераспределение изменило базовый адрес блока (то есть, если он не смог увеличить размер исходного блока и, следовательно, выделил новый больший блок в другом месте и скопировал в него старое содержимое). Следовательно, любые указатели на адреса в исходном блоке также больше не действительны.

Безопасность типов

маллок возвращает пустой указатель (пустота *), что указывает на то, что это указатель на область неизвестного типа данных. Использование преобразования типов требуется в C ++ из-за сильной системы типов, тогда как в C. это не относится к C. Можно "преобразовать" (см. преобразование типов ) этот указатель на конкретный тип:

int *ptr;ptr = маллок(10 * размер(*ptr));		/ * без приведения * /ptr = (int *)маллок(10 * размер(*ptr));	/ * с приведением * /

У выполнения такого гипса есть свои преимущества и недостатки.

Преимущества литья

  • Включение приведения может позволить программе или функции C компилироваться как C ++.
  • Актерский состав позволяет версии до 1989 года из маллок который первоначально вернул символ *.[11]
  • Приведение может помочь разработчику определить несоответствия в размере типа при изменении типа указателя назначения, особенно если указатель объявлен далеко от malloc () вызов (хотя современные компиляторы и статические анализаторы могут предупреждать о таком поведении, не требуя приведения[12]).

Недостатки литья

  • Согласно стандарту C приведение типов является избыточным.
  • Добавление приведения может замаскировать отказ от включения заголовка stdlib.h, в которой прототип функции за маллок находится.[11][13] При отсутствии прототипа маллок, стандарт C90 требует, чтобы компилятор C принимал маллок возвращает int. Если приведение отсутствует, C90 требует диагностики, когда это целое число присваивается указателю; однако, с приведением, эта диагностика не будет произведена, что скроет ошибку. На определенных архитектурах и моделях данных (например, LP64 в 64-битных системах, где длинный и указатели 64-битные и int является 32-битным), эта ошибка может фактически привести к неопределенному поведению, поскольку неявно объявлено маллок возвращает 32-битное значение, тогда как фактически определенная функция возвращает 64-битное значение. В зависимости от соглашений о вызовах и разметки памяти это может привести к разбивание стека. Эта проблема с меньшей вероятностью останется незамеченной в современных компиляторах, поскольку C99 не допускает неявных объявлений, поэтому компилятор должен произвести диагностику, даже если он предполагает int возвращаться.
  • Если тип указателя изменяется при его объявлении, также может потребоваться изменить все строки, где маллок называется и бросается.

Общие ошибки

Неправильное использование динамического распределения памяти часто может быть источником ошибок. Это могут быть ошибки безопасности или сбои программ, чаще всего из-за ошибки сегментации.

Наиболее частые ошибки следующие:[14]

Отсутствие проверки на сбой распределения
Выделение памяти не гарантируется, и вместо этого может возвращать нулевой указатель. Используя возвращаемое значение, не проверяя успешность выделения, вызывает неопределенное поведение. Обычно это приводит к сбою (из-за результирующей ошибки сегментации при разыменовании нулевого указателя), но нет никакой гарантии, что сбой произойдет, поэтому полагаться на это также может привести к проблемам.
Утечки памяти
Невозможность освободить память с помощью свободный приводит к накоплению не подлежащей повторному использованию памяти, которая больше не используется программой. Это расходует ресурсы памяти и может привести к сбоям выделения, когда эти ресурсы исчерпаны.
Логические ошибки
Все распределения должны соответствовать одному и тому же шаблону: распределение с использованием маллок, использование для хранения данных, освобождение с помощью свободный. Несоблюдение этого шаблона, например использование памяти после вызова свободный (висячий указатель ) или перед звонком на маллок (дикий указатель ), вызывающий свободный дважды («двойное освобождение») и т. д. обычно вызывает ошибку сегментации и приводит к сбою программы. Эти ошибки могут быть временными и трудными для отладки - например, освобожденная память обычно не восстанавливается немедленно ОС, и, таким образом, висячие указатели могут сохраняться некоторое время и, по-видимому, работать.

Кроме того, в качестве интерфейса, предшествующего стандартизации ANSI C, маллок а у друзей есть поведения, которые намеренно оставлены на усмотрение реализации, чтобы они определяли их сами. Один из них - это распределение нулевой длины, которое больше затрудняет перераспределить так как чаще всего устанавливается нулевой размер.[15] Хотя оба POSIX и Единая спецификация Unix требовать правильной обработки выделения нулевого размера, либо возвращая НОЛЬ или что-то еще, что можно безопасно освободить,[16] не все платформы обязаны соблюдать эти правила. Среди множества ошибок, к которым это привело, ошибка 2019 WhatsApp RCE был особенно заметен.[17] Чтобы сделать эти функции более безопасными, можно обернуть эти функции, просто проверив выделение нулевого размера и превратив их в выделения размера 1. (Возвращение НОЛЬ есть свои проблемы: в противном случае он указывает на сбой нехватки памяти. В случае перераспределить это означало бы, что исходная память не была перемещена и освобождена, что опять же не относится к размеру 0, что приводит к двойному освобождению.)[18]

Реализации

Реализация управления памятью во многом зависит от операционной системы и архитектуры. Некоторые операционные системы предоставляют распределитель для malloc, в то время как другие предоставляют функции для управления определенными областями данных. Один и тот же распределитель динамической памяти часто используется для реализации обоих маллок и оператор новый в C ++.[19]

На основе кучи

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

Метод кучи страдает несколькими внутренними недостатками, полностью проистекающими из фрагментация. Как и любой другой метод распределения памяти, куча становится фрагментированной; то есть в выделенном пространстве в куче будут разделы используемой и неиспользуемой памяти. Хороший распределитель попытается найти неиспользуемую область уже выделенной памяти для использования, прежде чем прибегать к расширению кучи. Основная проблема этого метода состоит в том, что куча имеет только два важных атрибута: основание или начало кучи в пространстве виртуальной памяти; и длина, или ее размер. Куча требует достаточно системной памяти, чтобы заполнить всю ее длину, и ее база никогда не может измениться. Таким образом, любые большие площади неиспользуемой памяти тратятся впустую. Куча может «застрять» в этом положении, если в конце кучи существует небольшой используемый сегмент, который может привести к потере любого количества адресного пространства. В схемах ленивого выделения памяти, которые часто встречаются в операционной системе Linux, большая куча не обязательно резервирует эквивалентную системную память; он будет делать это только при первой записи (чтение неотображенных страниц памяти возвращает ноль). Степень детализации зависит от размера страницы.

dlmalloc и ptmalloc

Дуг Ли разработал всеобщее достояние dlmalloc («Маллок Дуга Ли») как универсальный распределитель, начиная с 1987 года. Библиотека GNU C (glibc) происходит от ptmalloc Вольфрама Глогера ("pthreads malloc"), форка dlmalloc с улучшениями, связанными с потоками.[20][21][22] По состоянию на ноябрь 2019 года последней версией dlmalloc является версия 2.8.6 от августа 2012 года.[23]

dlmalloc - это распределитель граничных тегов. Память на куча выделяется как «куски», 8-байтовый выровнен структура данных который содержит заголовок и полезную память. Выделенная память содержит 8 или 16 байт служебных данных для размера блока и флагов использования (аналогично наркотик вектор ). Нераспределенные фрагменты также хранят указатели на другие свободные фрагменты в области полезного пространства, поэтому минимальный размер фрагмента составляет 16 байтов в 32-битных системах и 24/32 (зависит от выравнивания) байтов в 64-битных системах.[21][23](2.8.6, Минимальный выделенный размер)

Нераспределенная память сгруппирована в "мусорные ведра "аналогичных размеров, реализованные с помощью двойного списка блоков (с указателями, хранящимися в нераспределенном пространстве внутри блока). Бункеры сортируются по размеру на три класса:[21][23](Наложенные структуры данных)

  • Для запросов размером менее 256 байт (запрос "smallbin") используется простой двухуровневый распределитель наилучшего соответствия. Если в этом бункере нет свободных блоков, блок из следующего наивысшего бункера разделяется на две части.
  • Для запросов размером 256 байт и выше, но ниже mmap порог, dlmalloc с v2.8.0 использовать на месте побитовое дерево алгоритм ("treebin"). Если для удовлетворения запроса не осталось свободного места, dlmalloc пытается увеличить размер кучи, обычно с помощью BRK системный вызов. Эта функция была введена после создания ptmalloc (из v2.7.x), и в результате не является частью glibc, которая наследует старый распределитель наилучшего соответствия.
  • Для запросов, превышающих порог mmap (запрос "большой корзины"), память всегда выделяется с использованием mmap системный вызов. Порог обычно составляет 256 КБ.[24] Метод mmap предотвращает проблемы с огромными буферами, улавливающими небольшое выделение памяти в конце после истечения срока их действия, но всегда выделяет весь страница памяти, размер которой на многих архитектурах составляет 4096 байт.[25]

Разработчик игры Адриан Стоун утверждает, что dlmalloc, как распределитель граничных тегов, не подходит для консольных систем, которые имеют виртуальную память, но не имеют пейджинг по запросу. Это связано с тем, что его обратные вызовы для сжатия и увеличения пула (sysmalloc / systrim) не могут использоваться для выделения и фиксации отдельных страниц виртуальной памяти. В отсутствие пейджинга по запросу фрагментация становится более серьезной проблемой.[26]

Jemalloc FreeBSD и NetBSD

С FreeBSD 7.0 и NetBSD 5.0, старый маллок реализация (phkmalloc) была заменена на джемаллок, написанный Джейсоном Эвансом. Основной причиной этого была недостаточная масштабируемость phkmalloc с точки зрения многопоточности. Чтобы избежать конфликта блокировок, jemalloc использует отдельные "арены" для каждого ЦПУ. Эксперименты по измерению количества выделений в секунду в многопоточном приложении показали, что это позволяет линейно масштабировать его с количеством потоков, в то время как производительность как для phkmalloc, так и для dlmalloc была обратно пропорциональна количеству потоков.[27]

OpenBSD malloc

OpenBSD реализация маллок функция использует mmap. Для запросов размером больше одной страницы все распределение извлекается с помощью mmap; меньшие размеры назначаются из пулов памяти, поддерживаемых маллок внутри ряда "страниц корзины", также выделенных mmap.[28][нужен лучший источник ] По звонку свободный, память освобождается и не отображается из процесса адресное пространство с помощью munmap. Эта система предназначена для повышения безопасности за счет использования преимуществ рандомизация разметки адресного пространства и функции страницы пробелов, реализованные как часть OpenBSD mmap системный вызов и для обнаружения ошибок использования после освобождения - поскольку большой объем памяти полностью не отображается после его освобождения, дальнейшее использование вызывает ошибка сегментации и прекращение программы.

Клад маллок

Hoard - это распределитель, целью которого является масштабируемая производительность выделения памяти. Подобно распределителю OpenBSD, Hoard использует mmap исключительно, но управляет памятью фрагментами по 64 килобайта, называемыми суперблоками. Куча Hoard логически разделена на одну глобальную кучу и несколько куч для каждого процессора. Кроме того, существует локальный кэш потока, который может содержать ограниченное количество суперблоков. Распределяя только из суперблоков в локальной куче для каждого потока или процессора и перемещая в основном пустые суперблоки в глобальную кучу, чтобы их можно было повторно использовать другими процессорами, Hoard сохраняет низкий уровень фрагментации, обеспечивая при этом почти линейную масштабируемость с количеством потоков. .[29]

мималлок

А Открытый исходный код компактный универсальный распределитель памяти из Microsoft Research с упором на производительность.[30] В библиотеке около 11000 строки кода.

Кэширование потоков malloc (tcmalloc)

Каждый поток имеет локальное хранилище потока за небольшие отчисления. Для больших выделений mmap или sbrk может быть использован. TCMalloc, а маллок разработан Google,[31] имеет сборщик мусора для локального хранения мертвых потоков. TCMalloc считается более чем в два раза быстрее, чем ptmalloc в glibc для многопоточных программ.[32][33]

В ядре

Операционная система ядра необходимо выделять память так же, как это делают прикладные программы. Реализация маллок однако внутри ядра часто значительно отличается от реализаций, используемых библиотеками C. Например, буферы памяти могут соответствовать особым ограничениям, налагаемым DMA, или функция выделения памяти может быть вызвана из контекста прерывания.[34] Это требует маллок реализация тесно интегрирована с виртуальная память подсистема ядра операционной системы.

Переопределение malloc

Потому что маллок и его родственники могут оказывать сильное влияние на производительность программы, нередко переопределяют функции для конкретного приложения с помощью пользовательских реализаций, оптимизированных для шаблонов распределения приложений. Стандарт C не предоставляет возможности сделать это, но операционные системы нашли различные способы сделать это, используя динамическое связывание. Один из способов - просто связать другую библиотеку, чтобы переопределить символы. Другой, нанятый Система Unix V.3, это сделать маллок и свободный указатели функций, которые приложение может сбросить до пользовательских функций.[35]

Пределы размера размещения

Максимально возможный блок памяти маллок возможность выделения зависит от хост-системы, в частности от размера физической памяти и реализации операционной системы.

Теоретически наибольшее число должно быть максимальным значением, которое может храниться в size_t type, который представляет собой зависящее от реализации целое число без знака, представляющее размер области памяти. в C99 стандартный и более поздние версии, он доступен как SIZE_MAX постоянный от <stdint.h>. Хотя это не гарантируется ISO C, обычно 2 ^ (CHAR_BIT * размер (size_t)) - 1.

В системах glibc максимально возможный блок памяти маллок может выделить только половину этого размера, а именно 2 ^ (CHAR_BIT * размер (ptrdiff_t) - 1) - 1.[36]

Расширения и альтернативы

Реализации библиотеки C, поставляемые с различными операционными системами и компиляторами, могут иметь альтернативы и расширения к стандарту. маллок интерфейс. Среди них следует отметить:

  • alloca, который выделяет запрошенное количество байтов на стек вызовов. Соответствующей функции освобождения памяти не существует, поскольку обычно память освобождается, как только вызывающая функция возвращается. alloca присутствовал в системах Unix еще 32 / В (1978), но его использование может быть проблематичным в некоторых (например, встроенных) контекстах.[37] Хотя он поддерживается многими компиляторами, он не является частью ANSI-C стандартный и, следовательно, не всегда может быть переносимым. Это также может вызвать незначительные проблемы с производительностью: это приводит к кадрам стека переменного размера, так что оба указатели стека и кадра необходимо управлять (с кадрами стека фиксированного размера один из них является избыточным).[38] Более крупные распределения также могут увеличить риск неопределенного поведения из-за переполнение стека.[39] C99 предлагается массивы переменной длины в качестве альтернативного механизма распределения стека - однако в более поздних версиях эта функция стала необязательной. C11 стандарт.
  • POSIX определяет функцию posix_memalign который выделяет память с выравниванием, указанным вызывающим. Его распределения освобождаются свободный,[40] поэтому реализация обычно должна быть частью библиотеки malloc.

Смотрите также

Рекомендации

  1. ^ а б ISO / IEC 9899: 1999 спецификация (PDF). п. 313, § 7.20.3 «Функции управления памятью».
  2. ^ Годсе, Атул П .; Годсе, Дипали А. (2008). Расширенное программирование на C. п. 6-28: Технические публикации. п. 400. ISBN  978-81-8431-496-0.CS1 maint: location (связь)
  3. ^ Саммит, Стив. «Глава 11: Распределение памяти». Замечания по программированию на C. Получено 2020-07-11.
  4. ^ Страуструп, Бьярн (2008). Программирование: принципы и практика использования C ++. 1009, §27.4 Бесплатный магазин: Эддисон Уэсли. п. 1236. ISBN  978-0-321-54372-1.CS1 maint: location (связь)
  5. ^ "руководство по gcc". gnu.org. Получено 2008-12-14.
  6. ^ Брайан В. Керниган, Деннис М. Ричи, Язык программирования C, Прентис-Холл, 1978; Раздел 7.9 (страница 156) описывает каллок и cfree, а Раздел 8.7 (стр. 173) описывает реализацию для выделить и свободный.
  7. ^ выделить (3) – Версия 6 Unix Программиста Руководство
  8. ^ маллок (3) – Версия 7 Unix Программиста Руководство
  9. ^ Анонимный, Руководство программиста Unix, Vol. 1, Holt Reinhart and Winston, 1983 (авторские права принадлежат Bell Telephone Laboratories, 1983, 1979); В человек страница для маллок и т. д. приведено на странице 275.
  10. ^ alloca (3) – FreeBSD Библиотечные функции Руководство
  11. ^ а б "Литой маллок". Cprogramming.com. Получено 2007-03-09.
  12. ^ "clang: lib / StaticAnalyzer / Checkers / MallocSizeofChecker.cpp Исходный файл". clang.llvm.org. Получено 2018-04-01.
  13. ^ "comp.lang.c FAQ list · Вопрос 7.7b". C-FAQ. Получено 2007-03-09.
  14. ^ Рик, Кеннет (1997-08-04). Указатели на C (1-е изд.). Пирсон. ISBN  9780673999863.
  15. ^ «MEM04-C. Остерегайтесь распределений нулевой длины - SEI CERT C Coding Standard - Confluence». wiki.sei.cmu.edu.
  16. ^ «POSIX.1-2017: malloc». pubs.opengroup.org. Получено 2019-11-29.
  17. ^ Пробудился. «Как ошибка двойного бесплатного использования в WhatsApp превращается в RCE». Получено 2019-11-29.
  18. ^ Фелкер, Рич (2019-10-03). «Ух ты. WhatsApp RCE был неправильным поведением для realloc (p, 0), на котором настаивают многие реализации. Https://twitter.com/ottom6k/status/1179623539726524417…». Twitter. Получено 2019-11-29. Внешняя ссылка в | название = (помощь)
  19. ^ Александреску, Андрей (2001). Современный дизайн на C ++: применение общих шаблонов программирования и проектирования. Эддисон-Уэсли. п. 78.
  20. ^ "Домашняя страница malloc Вольфрама Глогера". malloc.de. Получено 2018-04-01.
  21. ^ а б c Кемпф, Мишель (2001). "Уловки вудо маллок". Phrack (57): 8. В архиве из оригинала от 22.01.2009. Получено 2009-04-29.
  22. ^ "Glibc: Внутреннее устройство Malloc". sourceware.org Trac. Получено 2019-12-01.
  23. ^ а б c Ли, Дуг. "Распределитель памяти". Получено 2019-12-01. HTTP для исходного кода
  24. ^ "Настраиваемые параметры Malloc". GNU. Получено 2009-05-02.
  25. ^ Сандерсон, Брюс (2004-12-12). «ОЗУ, виртуальная память, файл подкачки и все такое». Справка и поддержка Microsoft.
  26. ^ Стоун, Адриан. «Дыра, которую длмаллок не может заполнить». Игра Angst. Получено 2019-12-01.
  27. ^ Эванс, Джейсон (16 апреля 2006 г.). «Масштабируемая параллельная реализация malloc (3) для FreeBSD» (PDF). Получено 2012-03-18.
  28. ^ "libc / stdlib / malloc.c". Перекрестная ссылка BSD, OpenBSD src / lib /.
  29. ^ Бергер, Э.D .; МакКинли, К.С.; Blumofe, R.D .; Уилсон, П. Р. (ноябрь 2000 г.). Hoard: масштабируемый распределитель памяти для многопоточных приложений (PDF). АСПЛОС -IX. Материалы девятой международной конференции по архитектурной поддержке языков программирования и операционных систем. С. 117–128. CiteSeerX  10.1.1.1.4174. Дои:10.1145/378993.379232. ISBN  1-58113-317-0.
  30. ^ Microsoft выпускает оптимизированный malloc () с открытым исходным кодом - Slashdot
  31. ^ Домашняя страница TCMalloc
  32. ^ Гемават, Санджай; Menage, Пол; TCMalloc: Malloc с кэшированием потоков
  33. ^ Каллаган, Марк (18 января 2009 г.). «Высокая доступность MySQL: двойная пропускная способность sysbench с TCMalloc». Mysqlha.blogspot.com. Получено 2011-09-18.
  34. ^ "kmalloc () / kfree () включает / linux / slab.h". People.netfilter.org. Получено 2011-09-18.
  35. ^ Левин, Джон Р. (2000) [октябрь 1999]. «Глава 9: Общие библиотеки». Линкеры и загрузчики. Серия Морган Кауфманн в программной инженерии и программировании (1-е изд.). Сан-Франциско, США: Морган Кауфманн. ISBN  1-55860-496-0. OCLC  42413382. ISBN  978-1-55860-496-4. В архиве из оригинала от 05.12.2012. Получено 2020-01-12. Код: [1][2] Опечатки: [3]
  36. ^ "malloc: заставить malloc сбой с запросами больше, чем PTRDIFF_MAX". Исходное ПО Bugzilla. 2019-04-18. Получено 2020-07-30.
  37. ^ «Почему использование alloca () не считается хорошей практикой?». stackoverflow.com. Получено 2016-01-05.
  38. ^ Амарасингхе, Саман; Лейзерсон, Чарльз (2010). «6.172 Инженерия производительности программных систем, лекция 10». MIT OpenCourseWare. Массачусетский Институт Технологий. Архивировано из оригинал на 2015-06-22. Получено 2015-01-27.
  39. ^ "alloca (3) - справочная страница Linux". man7.org. Получено 2016-01-05.
  40. ^ posix_memalign - Справочник по системным интерфейсам, Единая спецификация UNIX, Выпуск 7 из Открытая группа

внешняя ссылка