Как я могу получить размер блока памяти, выделенного с помощью malloc ()? [дубликат]

Perl 6

sub join( $separator, @strings ){
  my $return = shift @strings;
  for @strings -> ( $string ){
    $return ~= $separator ~ $string;
  }
  return $return;
}

Да, я знаю это, бессмыслен, потому что Perl 6 уже имеет функцию соединения.

11
задан Community 23 May 2017 в 12:19
поделиться

9 ответов

Это не стандартно, но если в вашей библиотеке есть функция msize () , которая даст вам размер.

Распространенное решение - обернуть malloc с вашей собственной функцией, которая регистрирует каждый запрос вместе с размером и результирующим диапазоном памяти, в сборке выпуска вы можете вернуться к «реальному» malloc .

23
ответ дан 3 December 2019 в 00:44
поделиться

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

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

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

10
ответ дан 3 December 2019 в 00:44
поделиться

С gcc и компоновщиком GNU вы можете легко обернуть malloc

#include <stdlib.h>
#include <stdio.h>


void* __real_malloc(size_t sz);
void* __wrap_malloc(size_t sz)
{
    void *ptr;

    ptr = __real_malloc(sz);
    fprintf(stderr, "malloc of size %d yields pointer %p\n", sz, ptr);

    /* if you wish to save the pointer and the size to a data structure, 
       then remember to add wrap code for calloc, realloc and free */

    return ptr;
}

int main()
{
    char *x;
    x = malloc(103);

    return 0;
}

и скомпилировать с

gcc a.c -o a -Wall -Werror -Wl,--wrap=malloc

(конечно, это также будет работать с кодом C ++, скомпилированным с g ++, и с оператором new (через его искаженное имя), если хотите.)

Фактически, статически / динамически загружаемая библиотека также будет использовать ваш __ wrap_malloc .

5
ответ дан 3 December 2019 в 00:44
поделиться

Если вы не против грубого насилия ради отладки, вы можете #define макросов для перехвата вызовов malloc, освобождения и заполнения первых 4 байтов размером.

Чтобы мелодия

void *malloc_hook(size_t size) {
    size += sizeof (size_t);
    void *ptr = malloc(size);
    *(size_t *) ptr = size;
    return ((size_t *) ptr) + 1;
}

void free_hook (void *ptr) {
    ptr = (void *) (((size_t *) ptr) - 1);
    free(ptr);
}

size_t report_size(ptr) {
    return * (((size_t *) ptr) - 1);
}

, затем

#define malloc(x) malloc_hook(x)

и так далее

12
ответ дан 3 December 2019 в 00:44
поделиться

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

4
ответ дан 3 December 2019 в 00:44
поделиться

Средства проверки памяти, такие как memcheck Valgrind и TCMalloc от Google (часть проверки кучи) ) отслеживать подобные вещи.

Вы можете использовать TCMalloc для дампа профиля кучи, который показывает, где что-то было распределено, или вы можете просто проверить, чтобы ваша куча была одинаковой в двух точках выполнения программы, используя SameHeap () .

4
ответ дан 3 December 2019 в 00:44
поделиться

Частичное решение: в Windows вы можете использовать PageHeap для отслеживания доступа к памяти за пределами выделенный блок.

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

Как это получить: Загрузите и установите пакет Debugging Tools for Windows от Microsoft: http://www.microsoft.com/whdc/devtools/debugging/default.mspx

, затем запустите утилиту GFlags, перейдите на третью вкладку и введите имя исполняемого файла, затем нажмите клавишу. Установите флажок PageHeap, нажмите OK, и все готово.

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

2
ответ дан 3 December 2019 в 00:44
поделиться

Для этого не существует стандартной функции C. В зависимости от вашей платформы может быть непереносимый метод - какую ОС и библиотеку C вы используете?

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

4
ответ дан 3 December 2019 в 00:44
поделиться

Чтобы сделать то, что вы хотите, нужно БЫТЬ распределителем . Если вы отфильтруете все запросы, а затем запишите их для целей отладки, вы сможете узнать, что вы хотите, когда память будет освобождена.

Кроме того, вы можете проверить в конце программы, все ли выделенные блоки были освобождены, и, если нет, перечислить их. Такая амбициозная библиотека может даже принимать параметры FUNCTION и LINE через макрос, чтобы вы точно знали, где происходит утечка памяти.

Наконец, MSVCRT от Microsoft предоставляет отлаживаемую кучу с множеством полезных инструментов, которые вы можете использовать в отладочной версии для поиска проблем с памятью: http://msdn.microsoft.com/en-us/library/bebs9zyz.aspx

Вкл. Linux, вы можете использовать valgrind, чтобы найти множество ошибок. http://valgrind.org/

1
ответ дан 3 December 2019 в 00:44
поделиться