C и C ++: освобождение части выделенного указателя - PullRequest
6 голосов
/ 20 августа 2009

Допустим, у меня есть указатель, выделенный для хранения 4096 байтов. Как можно было бы освободить последние 1024 байта в C? Как насчет C ++? Что если вместо этого я захочу освободить первые 1024 байта и оставить остальные (на обоих языках)? Как насчет освобождения от середины (мне кажется, что для этого потребуется разделить его на два указателя, до и после освобожденной области).

Ответы [ 6 ]

12 голосов
/ 20 августа 2009

Не пытайтесь угадать управление памятью. Обычно он умнее тебя; -)

Единственное, чего вы можете достичь, - это первый сценарий «освобождения» последнего 1K

char * foo = malloc(4096);

foo = realloc(foo, 4096-1024);

Однако даже в этом случае НЕТ ГАРАНТИИ, что «foo» не изменится. Весь ваш 4K может быть освобожден, и realloc () может переместить вашу память в другое место, что сделает недействительными любые указатели на него, которые вы можете хранить.

Это справедливо как для C, так и для C ++, однако использование malloc () в C ++ является неприятным запахом кода, и большинство людей ожидает, что вы будете использовать new () для выделения памяти. А память, выделенная с помощью new (), не может быть realloc () ed - или, по крайней мере, не переносимым способом. STL векторы были бы намного лучшим подходом в C ++

5 голосов
/ 20 августа 2009

У вас нет «указателя, выделенного для хранения 4096 байт», у вас есть указатель на выделенный блок из 4096 байт.

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

Вы не можете изменить начальный адрес блока памяти malloc, который действительно задает ваш второй сценарий. Также нет способа разделить блок malloc.

Это ограничение API malloc / calloc / realloc / free - и реализации могут полагаться на эти ограничения (например, хранение бухгалтерской информации о распределении непосредственно перед начальным адресом что затруднит перемещение начального адреса.)

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

Для C ++, если вы выделяете память с помощью std::malloc, применяется приведенная выше информация. Если вы используете new и delete, вы выделяете хранилище и создаете объекты, поэтому изменение размера выделенного блока не имеет смысла - объекты в C ++ имеют фиксированный размер.

2 голосов
/ 20 августа 2009

Если у вас n байтов malloc памяти, вы можете realloc m байтов (где m <<code>n) и, таким образом, выбросить последние n-m байтов.

Чтобы отбросить с самого начала, вы можете malloc новый меньший буфер и memcpy желаемых байт, а затем free оригинал.

Последний вариант также доступен с использованием C ++ new и delete. Он также может эмулировать первый realloc кейс.

1 голос
/ 20 августа 2009

http://en.wikipedia.org/wiki/New_(C%2B%2B)

РЕЗЮМЕ: В отличие от realloc C, это невозможно напрямую перераспределить память выделена новым []. Расширить или уменьшить размер блока, один необходимо выделить новый блок адекватного размер, скопируйте старую память и удалить старый блок. Стандарт C ++ библиотека предоставляет динамический массив, который может быть расширен или уменьшен в его std :: vector template.

1 голос
/ 20 августа 2009

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

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

1 голос
/ 20 августа 2009

Вы можете сделать его короче с помощью realloc (). Я не думаю, что остальное возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...