Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

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

Обсуждение ряда полезных инструментов для отладки динамической памяти см в разделе 15.5.2 «Отладчики выделения памяти».

3.2.1.4. Изменение размера:

realloc

Динамическая память имеет существенное преимущество перед статически объявленными массивами, поскольку это позволяет использовать столько памяти, сколько нужно, и не больше. Не нужно объявлять глобальный, статический или локальный массив фиксированного размера и надеяться, что он: (а) достаточно большой и (б) не слишком большой. Вместо этого можно выделить ровно столько, сколько нужно, не больше и не меньше.

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

realloc
. Продолжая пример с
coordinates
, типичный код выглядит следующим образом:

int new_count;

size_t new_amount;

struct coord *newcoords; /* установить, например: */

new_count = count * 2; /* удвоить размер памяти */

new_amount = new_count * sizeof(struct coord);

newcoords =

 (struct coord*)realloc(coordinates, new_amount);

if (newcoords == NULL) {

 /* сообщить об ошибке, восстановить или прервать */

}

coordinates = newcoords;

/* продолжить использование coordinates ... */

Как и в случае с

malloc
, шаги стереотипны по природе и сходны по идее.

1. Вычислить новый выделяемый размер в байтах.

2. Вызвать

realloc
с оригинальным указателем, полученным от
malloc
(или от
calloc
или предыдущего вызова
realloc
) и с новым размером.

3. Привести тип и присвоить возвращенное

realloc
значение. Подробнее обсудим дальше.

4. Как и для

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

При увеличении размера блока памяти

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

В любом случае вы можете предположить, что если

realloc
не возвращает
NULL
, старые данные были скопированы для вас в новый участок памяти. Более того, старый указатель больше недействителен, как если бы вы вызвали
free
с ним, и использовать его больше не следует. Это верно для всех указателей на этот блок данных, а не только для того, который использовался при вызове
free
.

Возможно, вы заметили, что в нашем примере для указания на измененный блок памяти использовалась отдельная переменная. Можно было бы (хотя это плохая идея) использовать ту же самую переменную, как здесь:

coordinates = realloc(coordinates, new_amount);

Это плохо по следующей причине. Когда

realloc
возвращает
NULL
, первоначальный указатель все еще действителен; можно безопасно продолжить использовать эту память. Но если вы повторно используете ту же самую переменную и
realloc
возвращает
NULL
, вы теряете указатель на первоначальную память. Эту память больше нельзя использовать. Что еще важнее, эту память невозможно освободить! Это создает утечку памяти, которую нужно избежать.

Для версии

realloc
в стандартном С есть некоторые особые случаи: когда аргумент
ptr
равен
NULL
,
realloc
действует подобно
malloc
и выделяет свежий блок памяти. Когда аргумент
size
равен 0,
realloc
действует подобно
free
и освобождает память, на которую указывает
ptr
. Поскольку (а) это может сбивать с толку и (б) более старые системы не реализуют эту возможность, мы рекомендуем использовать
malloc
, когда вы имеете в виду
malloc
, и
free
, когда вы имеете в виду
free
.

Вот другой довольно тонкий момент [42] . Рассмотрим процедуру, которая содержит статический указатель на динамически выделяемые данные, которые время от времени должны расти. Процедура может содержать также автоматические (т.е. локальные) указатели на эти данные. (Для краткости, мы опустим проверки ошибок. В коде продукта не делайте этого.) Например:

void manage_table(void) {

 static struct table *table;

 struct table *cur, *p;

42

Он получен от реальной практики работы с

gawk
Примеч. автора.

 int i;

 size_t count;

 ...

 table =

(struct table*)malloc(count * sizeof(struct table));

 /* заполнить таблицу */

 cur = &table[i]; /* указатель на 1-й элемент */

 ...

 cur->i = j; /* использование указателя */

 ...

 if (/* некоторое условие */) {

/* нужно увеличить таблицу */

Поделиться:
Популярные книги

Лишённые плоти

Макдермид Вэл
6. Тони Хилл и Кэрол Джордан
Детективы:
маньяки
7.71
рейтинг книги
Лишённые плоти

Мастер Трав III

Мордорский Ваня
3. Мастер Трав
Фантастика:
фэнтези
рпг
фантастика: прочее
попаданцы
5.75
рейтинг книги
Мастер Трав III

Сильнейший Столп Империи. Книга 2

Ермоленков Алексей
2. Сильнейший Столп Империи
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Сильнейший Столп Империи. Книга 2

На границе империй. Том 7

INDIGO
7. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
6.75
рейтинг книги
На границе империй. Том 7

Атаман царского Спецназа

Корчевский Юрий Григорьевич
Боевая фантастика Ю. Корчевского
Фантастика:
боевая фантастика
попаданцы
альтернативная история
6.00
рейтинг книги
Атаман царского Спецназа

Моров. Том 4

Кощеев Владимир
3. Моров
Фантастика:
фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Моров. Том 4

Второгодка. Книга 2. Око за око

Ромов Дмитрий
2. Второгодка
Фантастика:
героическая фантастика
альтернативная история
фэнтези
5.00
рейтинг книги
Второгодка. Книга 2. Око за око

Ты - наша

Зайцева Мария
1. Наша
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Ты - наша

Глава рода

Шелег Дмитрий Витальевич
5. Живой лёд
Фантастика:
боевая фантастика
6.55
рейтинг книги
Глава рода

Князь Целитель 3

Ткачев Андрей Юрьевич
3. Князь Целитель
Фантастика:
боевая фантастика
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Князь Целитель 3

Туполев

Бодрихин Николай Георгиевич
1327. Жизнь замечательных людей
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Туполев

Черный Маг Императора 10

Герда Александр
10. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 10

Найденыш

Шмаков Алексей Семенович
2. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Найденыш

Кодекс Охотника. Книга XXXVII

Винокуров Юрий
37. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXVII