Освобождение частей динамически распределенных блоков?

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

Например:

char* a = malloc (40);
//b points to the split second half of the block, or to NULL if it's beyond the end
//a points to a area of 10 bytes
b = partial_free (a+10, /*size*/ 10) 

Мысли о том, почему это мудро / неразумно / сложно? Способы сделать это?

Мне кажется, что это может быть полезно.

Спасибо!

===== edit ===== после некоторых исследований кажется, что распределитель bootmem для ядра linux допускает нечто похожее на эту операцию с вызовом bootmem_free. Итак, мне любопытно - почему распределитель bootmem позволяет это, а ANSI C - нет?

3 ответа

Нет такой функции, которая бы позволила частично освободить память.
Однако вы можете использовать realloc() для изменения размера памяти.

Из стандарта c:

7.22.3.5 realloc функция

#include <stdlib.h>
void *realloc(void *ptr, size_t size);

Функция realloc освобождает старый объект, на который указывает ptr, и возвращает указатель на новый объект, размер которого определяется размером. Содержимое нового объекта должно быть таким же, как и у старого объекта до освобождения, до меньшего из нового и старого размеров. Любые байты в новом объекте, превышающие размер старого объекта, имеют неопределенные значения.

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

Теперь, если вы выделили немного памяти:

char * tmp = malloc(2048); 

и вы намереваетесь освободить первую 1 Кб памяти, вы можете сделать:

tmp = realloc(foo, 2048-1024);

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

Теперь я не уверен насчет точной реализации realloc, но, насколько я понимаю, код:

myptr = malloc( x - y );

на самом деле malloc новый буфер памяти размера x-y затем копирует байты, которые соответствуют memcpy и наконец free с оригинальной выделенной памяти.

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

Во-первых, я не могу вспомнить ни одной ситуации, когда вам, вероятно, понадобится такая вещь (когда существует realloc для увеличения / уменьшения памяти, как указано в ответах).

Я хотел бы добавить еще одну вещь. В любых реализациях, которые я видел в подсистеме malloc (которую, я признаю, не так много), malloc и free реализованы так, чтобы зависеть от того, что называется префиксным байтом (байтами). Таким образом, независимо от того, какой адрес вам возвращает malloc, внутренняя подсистема malloc будет выделять некоторые дополнительные байты памяти перед возвращенным вам адресом, чтобы хранить информацию о проверке работоспособности, которая включает количество выделенных байтов и, возможно, какую политику выделения вы используете. (если ваша ОС поддерживает несколько политик выделения памяти) и т. д. Когда вы говорите что-то вроде free (x байтов), подсистема malloc возвращается к просмотру байта префикса для проверки работоспособности, и только если она находит префикс на месте, освобождается успешно получилось. Следовательно, он не позволит вам освободить некоторое количество блоков, начинающихся между ними.

Другие вопросы по тегам