MALLOC_INFO(3) Руководство программиста Linux MALLOC_INFO(3)

ИМЯ

malloc_info - экспортирует состояние malloc в поток

ОБЗОР

#include <malloc.h>
int malloc_info(int options, FILE *stream);

ОПИСАНИЕ

Функция malloc_info() экспортирует строку XML, описывающую текущее состояние реализации выделения памяти вызывающего. Строка печатается в файловый поток stream. В экспортируемой строке содержится информация о всех областях (arenas) (смотрите malloc(3)).

В текущей реализации значение options должно быть равно нулю.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении malloc_info() возвращается 0; при ошибке возвращается -1, а в errno помещается код ошибки.

ОШИБКИ

Значение options не равно.

ВЕРСИИ

Функция malloc_info() впервые появилась в glibc 2.10.

АТРИБУТЫ

Описание терминов данного раздела смотрите в attributes(7).

Интерфейс Атрибут Значение
malloc_info() Безвредность в нитях MT-Safe

СООТВЕТСТВИЕ СТАНДАРТАМ

Эта функция является расширением GNU.

ЗАМЕЧАНИЯ

Информация о выделении памяти предоставляется в виде строки XML (а не в структуре C), так как структура со временем может меняться (при изменении в реализации). Возвращаемая строка XML содержит поле версии.

Для отправки вывода malloc_info() в буфер памяти, а не в файл можно использовать функцию open_memstream(3).

Функция malloc_info() разработана для компенсации нехватки данных из malloc_stats(3) и mallinfo(3).

ПРИМЕР

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

Чтобы показать состояние выделения памяти программа дважды вызывает malloc_info(). Первый раз вызов делается до создания нитей и выделения памяти. Второй вызов выполняется после того, как все нити выделят память.

В следующем примере аргументами командной строки задаётся создание одной дополнительной нити и что главная и дополнительная нить выделяют 10000 блоков памяти. После того, как блоки памяти выделены, malloc_info() показывает состояние двух областей выделения.

$ getconf GNU_LIBC_VERSION
glibc 2.13
$ ./a.out 1 10000 100
============ до выделения блоков ============
<malloc version="1">
<heap nr="0">
<sizes>
</sizes>
<total type="fast" count="0" size="0"/>
<total type="rest" count="0" size="0"/>
<system type="current" size="135168"/>
<system type="max" size="135168"/>
<aspace type="total" size="135168"/>
<aspace type="mprotect" size="135168"/>
</heap>
<total type="fast" count="0" size="0"/>
<total type="rest" count="0" size="0"/>
<system type="current" size="135168"/>
<system type="max" size="135168"/>
<aspace type="total" size="135168"/>
<aspace type="mprotect" size="135168"/>
</malloc>
============ после выделения блоков ============
<malloc version="1">
<heap nr="0">
<sizes>
</sizes>
<total type="fast" count="0" size="0"/>
<total type="rest" count="0" size="0"/>
<system type="current" size="1081344"/>
<system type="max" size="1081344"/>
<aspace type="total" size="1081344"/>
<aspace type="mprotect" size="1081344"/>
</heap>
<heap nr="1">
<sizes>
</sizes>
<total type="fast" count="0" size="0"/>
<total type="rest" count="0" size="0"/>
<system type="current" size="1032192"/>
<system type="max" size="1032192"/>
<aspace type="total" size="1032192"/>
<aspace type="mprotect" size="1032192"/>
</heap>
<total type="fast" count="0" size="0"/>
<total type="rest" count="0" size="0"/>
<system type="current" size="2113536"/>
<system type="max" size="2113536"/>
<aspace type="total" size="2113536"/>
<aspace type="mprotect" size="2113536"/>
</malloc>

Исходный код программы

#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <malloc.h>
#include <errno.h>
static size_t blockSize;
static int numThreads, numBlocks;
#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \

                        } while (0)
static void *
thread_func(void *arg)
{

    int j;

    int tn = (int) arg;

    /* Множитель '(2 + tn)' для обеспечения того, что каждая

       нить (включая главную) выделяет разное количество памяти */

    for (j = 0; j < numBlocks; j++)

        if (malloc(blockSize * (2 + tn)) == NULL)

            errExit("malloc-thread");

    sleep(100);         /* Спим, пока главная нить не завершит работу */

    return NULL;
}
int
main(int argc, char *argv[])
{

    int j, tn, sleepTime;

    pthread_t *thr;

    if (argc < 4) {

        fprintf(stderr,

                "%s num-threads num-blocks block-size [sleep-time]\n",

                argv[0]);

        exit(EXIT_FAILURE);

    }

    numThreads = atoi(argv[1]);

    numBlocks = atoi(argv[2]);

    blockSize = atoi(argv[3]);

    sleepTime = (argc > 4) ? atoi(argv[4]) : 0;

    thr = calloc(numThreads, sizeof(pthread_t));

    if (thr == NULL)

        errExit("calloc");

    printf("============ до выделения блоков ============\n");

    malloc_info(0, stdout);

    /* Создаём нити, которые выделяют разное количество памяти  */

    for (tn = 0; tn < numThreads; tn++) {

        errno = pthread_create(&thr[tn], NULL, thread_func,

                               (void *) tn);

        if (errno != 0)

            errExit("pthread_create");

        /* если мы добавим задержку после запуска каждой нити,

           то нити, вероятно,  не будут бороться за мьютекс malloc,

           и поэтому дополнительные области выделены

           не будут (смотрите malloc(3)) */

        if (sleepTime > 0)

            sleep(sleepTime);

    }

    /* главная нить также выделяет память */

    for (j = 0; j < numBlocks; j++)

        if (malloc(blockSize) == NULL)

            errExit("malloc");

    sleep(2);           /* ждём, чтобы потоки успели

                           выделить память */

    printf("\n============ после выделения блоков ============\n");

    malloc_info(0, stdout);

    exit(EXIT_SUCCESS);
}

СМОТРИТЕ ТАКЖЕ

mallinfo(3), malloc(3), malloc_stats(3), mallopt(3), open_memstream(3)

2019-03-06 GNU