mallopt(3)

НАИМЕНОВАНИЕ
mallopt - задаёт параметры выделения памяти

БИБЛИОТЕКА
Стандартная библиотека языка C (libc, -lc)

ОБЗОР
#include <malloc.h>

int mallopt(int param, int value);

ОПИСАНИЕ
Функция mallopt() подстраивает параметры, которые управляют поведением функций выделения памяти (смотрите malloc(3)). В аргументе param указывается изменяемый параметр, а в value — новое значение этого параметра.

В param можно указать следующие значения:

M_ARENA_MAX
    Если этот параметр не равен нулю, то он определяет жёсткое ограничение на максимальное количество площадок (arenas), которое можно создать. Площадка представляет собой общий набор буферов (pool) памяти, который может использовать вызов malloc(3) (и подобные) для обслуживания запросов выделения. Площадки безопасны в нитях и поэтому могут использоваться при одновременных запросах выделения. Нужно соблюдать соотношение между количеством нитей и количеством площадок. Чем больше площадок, тем меньше состязаний между нитями, но большее потребление памяти.

    Значение по умолчанию данного параметра равно 0, то есть ограничение на количество площадок будет определяться по M_ARENA_TEST.

    Этот параметр доступен начиная с glibc 2.10 при указании --enable-experimental-malloc, и начиная с glibc 2.15 — по умолчанию. В некоторых версиях механизм выделения не имел ограничения на количество создаваемых площадок (например, в CentOS 5, RHEL 5).

    При использовании более новых версий glibc приложения могут, в некоторых случаях, встретить высокую состязательность при доступе к площадкам. В этих случаях может быть выгодно увеличить M_ARENA_MAX для соответствия количеству нитей. Такое поведение подобно стратегиям, используемым tcmalloc и jemalloc (например, общие наборы буферов выделения для каждой нити).

M_ARENA_TEST
    Этим параметром определяется значение на количество создаваемых площадок; в соответствии с ним будут исследоваться системные настройки для оценки жёсткого ограничения на количество создаваемых площадок (определение площадки смотрите в описании M_ARENA_MAX).

    Вычисленное жёсткое ограничение на площадки определяется реализацией и, обычно, кратно количеству доступных ЦП. После вычисления жёсткого ограничения, результат окончательный и ограничивает общее количество площадок.

    Значение по умолчанию для параметра M_ARENA_TEST равно 2 в системах, где sizeof(long) равно 4; в противном случае значение по умолчанию равно 8.

    Этот параметр доступен начиная с glibc 2.10 при указании --enable-experimental-malloc, и начиная с glibc 2.15 — по умолчанию.

    Значение M_ARENA_TEST не используется, если M_ARENA_MAX не равно нулю.

M_CHECK_ACTION
    Значение данного параметра управляет тем, как glibc действует при обнаружении различных программных ошибок (например, освобождение одного указателя дважды). Поведение glibc задаётся тремя битами (2, 1 и 0) указанного значения:

    Бит 0
        Если этот бит установлен, то печатается сообщение в stderr с подробностями ошибки. Сообщение начинается со строки «*** glibc detected ***», далее идёт имя программы, имя функции выделения памяти, в которой возникла ошибка, краткое описание ошибки и адрес памяти, где обнаружена ошибка.

    Бит 1
        If this bit is set, then, after printing any error message specified by bit 0, the program is terminated by calling abort(3). Since glibc 2.4, if bit 0 is also set, then, between printing the error message and aborting, the program also prints a stack trace in the manner of backtrace(3), and prints the process's memory mapping in the style of /proc/pid/maps (see proc(5)).

    Бит 2 (начиная с glibc 2.4)
        Этот бит учитывается только если установлен бит 0. Если данный бит установлен, то выдаваемое сообщение об ошибке упрощается до имени функции, где обнаружена ошибка и короткого описания ошибки.

    Оставшиеся биты в value игнорируются.

    Объединяя выше описанное, получаются следующие числовые значения, влияющие на M_CHECK_ACTION:

    0   Игнорировать условия ошибки; продолжить выполнение (с неопределенными результатами).

    1   Вывести подробное сообщение об ошибке и продолжить выполнение.

    2   Прервать программу.

    3   Вывести подробное сообщение об ошибке, трассировку стека и отображения памяти, а затем прервать программу.

    5   Вывести простое сообщение об ошибке и продолжить выполнение.

    7   Вывести простое сообщение об ошибке, трассировку стека и отображения памяти, и прервать программу.

    Since glibc 2.3.4, the default value for the M_CHECK_ACTION parameter is 3. In glibc 2.3.3 and earlier, the default value is 1.

    Использование ненулевого значения M_CHECK_ACTION может быть полезно, так как в противном случае падение может случиться позднее и будет сложно отследить реальную причину проблемы.

M_MMAP_MAX
    Данным параметром задаётся максимальное количество запросов выделения, которые может одновременно выполнить mmap(2). Этот параметр существует, так как в некоторых системах ограничено количество внутренних таблиц, используемых mmap(2), и использование больше определённого количество снижает производительность.

    По умолчанию значение равно 65536; оно не имеет какого-то специального обоснования и служит только как предохранитель. Присвоение этому параметру 0 отключает использование mmap(2) для обслуживания запросов больших выделений.

M_MMAP_THRESHOLD
    Для выделений, которые больше или равны M_MMAP_THRESHOLD (в байтах) и не могут быть получены из списка свободных, то функции выделения памяти вместо mmap(2) используют sbrk(2) для увеличения пространства данных программы.

    Выделяемая с помощью mmap(2) память имеет значительное преимущество в том, что выделенные блоки памяти можно всегда независимо освободить и вернуть системе (по сравнению с кучей, которую можно обрезать только, если память свободна в конце). С другой стороны, есть несколько отрицательных моментов при использовании mmap(2): освобождённое пространство не возвращается в список свободного для повторного выделения позже; память может траться впустую, так как выделения mmap(2) должны быть кратны размеру страницы; ядро должно выполнять ресурсоёмкую задачу по обнулению памяти, выделяемой через mmap(2). Баланс этих факторов учтён в значении по умолчанию для параметра M_MMAP_THRESHOLD — 128*1024.

    Нижний предел данного параметра равен 0. Верхний предел DEFAULT_MMAP_THRESHOLD_MAX: 512*1024 в 32-битных системах и 4*1024*1024*sizeof(long) в 64-битных системах.

    Note: Nowadays, glibc uses a dynamic mmap threshold by default. The initial value of the threshold is 128*1024, but when blocks larger than the current threshold and less than or equal to DEFAULT_MMAP_THRESHOLD_MAX are freed, the threshold is adjusted upward to the size of the freed block. When dynamic mmap thresholding is in effect, the threshold for trimming the heap is also dynamically adjusted to be twice the dynamic mmap threshold. Dynamic adjustment of the mmap threshold is disabled if any of the M_TRIM_THRESHOLD, M_TOP_PAD, M_MMAP_THRESHOLD, or M_MMAP_MAX parameters is set.

M_MXFAST (начиная с glibc 2.3)
    Задаёт верхний порог запросов выделения памяти, которые обрабатываются с помощью «fastbins» (значение параметра измеряется в байтах). Fastbins — это области хранилища, которые содержат освобождённые блоки памяти одного размера и не объединяют смежные свободные блоки. Последующее перераспределение блоков одного размера при выделении из fastbin может обрабатываться очень быстро, хотя из-за этого может увеличиться фрагментация памяти и общее количество памяти программы.

    По умолчанию значение параметра равно 64*sizeof(size_t)/4 (т. е., 64 на 32-битных архитектурах). Диапазон значений параметра: 0 - 80*sizeof(size_t)/4. Присваивание M_MXFAST значения 0 отключает использование fastbins.

M_PERTURB (начиная с glibc 2.4)
    Если этому параметру присвоено ненулевое значение, то байты выделенной памяти (кроме выделенных через calloc(3)) инициализируются дополнением значения в наименее значимом байте value, и при освобождении памяти с помощью free(3) освобождённым байтам присваивается значение наименее значимого байта value. Это может быть полезно для обнаружения ошибок, когда программа некорректно полагается на то, что выделенная памяти инициализируется нулями или повторно использует значения уже освобождённой памяти.

    Значение по умолчанию для этого параметра равно 0.

M_TOP_PAD
    Данным параметром определяется количество заполнения при вызове sbrk(2) для изменения пространства данных программы (измеряется в байтах). Данный параметр полезен в следующих случаях:

    •   Когда пространство данных программы увеличивается, то M_TOP_PAD байт добавляется к запросу sbrk(2).

    •   Когда обрезается куча в следствии вызова free(3) (смотрите описание M_TRIM_THRESHOLD), то это количество пространства предохраняется вверху кучи.

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

    Изменение M_TOP_PAD — компромисс между увеличением количества системных вызовов (если значение параметра занижено) и тратой неиспользуемой памяти сверху кучи (если значение параметра завышено).

    Значение по умолчанию этого параметра равно 128*1024.

M_TRIM_THRESHOLD
    Когда количество непрерывной свободной памяти сверху кучи вырастает до значительных размеров функция free(3) вызывает sbrk(2) для освобождения этой памяти обратно в систему (это может быть полезно в программах, которые работают длительное время после освобождения значительного количества памяти). Параметром M_TRIM_THRESHOLD задаётся минимальный размер (в байтах), которого должен достигнуть блок памяти, чтобы вызвался sbrk(2) для обрезания кучи.

    Значение по умолчанию этого параметра равно 128*1024. Установка M_TRIM_THRESHOLD равным -1 отключает обрезку.

    Изменение M_TRIM_THRESHOLD — компромисс между увеличением количества системных вызовов (если значение параметра занижено) и тратой неиспользуемой памяти сверху кучи (если значение параметра завышено).

  Переменные окружения
Параметры, управляющие mallopt(), можно изменить и через переменные окружения. Использование этих переменных позволяет изменять работу программы без пересборки из исходного кода. В целях эффективной работы эти переменные должны быть определены до первого вызова функции выделения памяти (если этот же параметр изменяется через mallopt(), то вызов mallopt() имеет приоритет). В целях безопасности, эти переменные игнорируются для программ с установленными битами set-user-ID и set-group-ID.

Используются следующие переменные окружения (обратите внимание на подчёркивание в конце некоторых переменных):

MALLOC_ARENA_MAX
    Управляет параметром M_ARENA_MAX, аналогично вызову mallopt().

MALLOC_ARENA_TEST
    Управляет параметром M_ARENA_TEST, аналогично вызову mallopt().

MALLOC_CHECK_
    Эта переменная окружения управляет тем же параметром что и mallopt() M_CHECK_ACTION. Если эта переменная установлена в ненулевое значение, то будет использоваться особенная реализация функций выделения памяти (это достигается использованием функции malloc_hook(3)). Эта реализация выполняет дополнительные проверки ошибок, но она медленнее чем стандартный набор функций выделения памяти (эта реализация не способна обнаружить все возможные ошибки; утечки памяти всё ещё возможны).

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

    В целях безопасности по умолчанию переменная MALLOC_CHECK_ игнорируется для программ с установленными битами set-user-ID и set-group-ID. Однако, если существует файл /etc/suid-debug (содержимое файла не важно), то MALLOC_CHECK_ учитывается и для программ с установленными битами set-user-ID и set-group-ID.

MALLOC_MMAP_MAX_
    Управляет параметром M_MMAP_MAX, аналогично вызову mallopt().

MALLOC_MMAP_THRESHOLD_
    Управляет параметром M_MMAP_THRESHOLD, аналогично вызову mallopt().

MALLOC_PERTURB_
    Управляет параметром M_PERTURB, аналогично вызову mallopt().

MALLOC_TRIM_THRESHOLD_
    Управляет параметром M_TRIM_THRESHOLD, аналогично вызову mallopt().

MALLOC_TOP_PAD_
    Управляет параметром M_TOP_PAD, аналогично вызову mallopt().

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении mallopt() возвращается 1. При ошибке возвращается 0.

ОШИБКИ
При ошибке значение errno не изменяется.

ВЕРСИИ
A similar function exists on many System V derivatives, but the range of values for param varies across systems. The SVID defined options M_MXFAST, M_NLBLKS, M_GRAIN, and M_KEEP, but only the first of these is implemented in glibc.

СТАНДАРТЫ
Отсутствуют.

ИСТОРИЯ
glibc 2.0.

ОШИБКИ
Неправильное значение param не вызывает ошибки.

Ошибка вычисления внутри реализации glibc означает, что вызов:

    mallopt(M_MXFAST, n)

не приведёт к тому, что из fastbins будет выделяться память до размера n. Чтобы это сработало, n должно быть округлено до следующего множителя большего или равного (2k+1)*sizeof(size_t), где k — целое число.

Если mallopt() используется для установки M_PERTURB, то, как и ожидалось, байты свободной памяти инициализируются дополнением байта из value, и когда эта память освобождается, байты области инициализируются байтом, указанным в value. Однако, в реализации есть ошибка выхода за sizeof(size_t): вместо инициализации точного блока памяти освобождаемом вызовом free(p), блок начинает инициализироваться с p+sizeof(size_t).

ПРИМЕРЫ
Представленная далее программа показывает использование M_CHECK_ACTION. Если программе передаётся аргумент командной строки (целое число), то этот аргумент используется для установки значения параметра M_CHECK_ACTION. При этом программа выделяет блок памяти и освобождает его дважды (ошибка).

Следующий сеанс в оболочке показывает работу программы с glibc и значением по умолчанию для M_CHECK_ACTION:

    $ ./a.out
    main(): возвращение из первого вызова free()
    *** glibc detected *** ./a.out: double free or corruption (top): 0x09d30008 ***
    ======= Backtrace: =========
    /lib/libc.so.6(+0x6c501)[0x523501]
    /lib/libc.so.6(+0x6dd70)[0x524d70]
    /lib/libc.so.6(cfree+0x6d)[0x527e5d]
    ./a.out[0x80485db]
    /lib/libc.so.6(__libc_start_main+0xe7)[0x4cdce7]
    ./a.out[0x8048471]
    ======= Memory map: ========
    001e4000-001fe000 r-xp 00000000 08:06 1083555    /lib/libgcc_s.so.1
    001fe000-001ff000 r--p 00019000 08:06 1083555    /lib/libgcc_s.so.1
    [some lines omitted]
    b7814000-b7817000 rw-p 00000000 00:00 0
    bff53000-bff74000 rw-p 00000000 00:00 0          [stack]
    Aborted (core dumped)

В этом запуске показаны результаты при других значениях M_CHECK_ACTION:

    $ ./a.out 1             # показ ошибки и продолжение
    main(): возвращение из первого вызова free()
    *** glibc detected *** ./a.out: double free or corruption (top): 0x09cbe008 ***
    main(): возвращение из второго вызова free()
    $ ./a.out 2             # прерывание без показа ошибки
    main(): возвращение из первого вызова free()
    Aborted (core dumped)
    $ ./a.out 0             # игнорирование ошибки и продолжение
    main(): возвращение из первого вызова free()
    main(): возвращение из второго вызова free()

При этом запуске показано как изменить тот же параметр с помощью переменной окружения MALLOC_CHECK_:

    $ MALLOC_CHECK_=1 ./a.out
    main(): возвращение из первого вызова free()
    *** glibc detected *** ./a.out: free(): invalid pointer: 0x092c2008 ***
    main(): возвращение из второго вызова free()

  Исходный код программы
    #include <malloc.h>
    #include <stdio.h>
    #include <stdlib.h>

    int
    main(int argc, char *argv[])
    {
        char *p;

        if (argc > 1) {
            if (mallopt(M_CHECK_ACTION, atoi(argv[1])) != 1) {
                fprintf(stderr, "mallopt() failed");
                exit(EXIT_FAILURE);
            }
        }

        p = malloc(1000);
        if (p == NULL) {
            fprintf(stderr, "malloc() failed");
            exit(EXIT_FAILURE);
        }

        free(p);
        printf("%s(): returned from first free() call\n", __func__);

        free(p);
        printf("%s(): returned from second free() call\n", __func__);

        exit(EXIT_SUCCESS);
    }

СМОТРИТЕ ТАКЖЕ
mmap(2), sbrk(2), mallinfo(3), malloc(3), malloc_hook(3), malloc_info(3), malloc_stats(3), malloc_trim(3), mcheck(3), mtrace(3), posix_memalign(3)

ПЕРЕВОД
Русский перевод этой страницы руководства разработал(и) aereiae <aereiae@gmail.com>, Alexey <a.chepugov@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy S. Seregin <dseregin@59.ru>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, ITriskTI <ITriskTI@gmail.com>, Max Is <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru>, Иван Павлов <pavia00@gmail.com>, Малянов Евгений Викторович <maljanow@outlook.com> и Kirill Rekhov <krekhov.dev@gmail.com>

Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков (<debian-l10n-russian@lists.debian.org>).