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

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

Жанры

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 (/* некоторое условие */) {

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

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

Последний попаданец 2

Зубов Константин
2. Последний попаданец
Фантастика:
юмористическая фантастика
попаданцы
рпг
7.50
рейтинг книги
Последний попаданец 2

"Фантастика 2023-123". Компиляция. Книги 1-25

Харников Александр Петрович
Фантастика 2023. Компиляция
Фантастика:
боевая фантастика
альтернативная история
5.00
рейтинг книги
Фантастика 2023-123. Компиляция. Книги 1-25

Мама из другого мира. Дела семейные и не только

Рыжая Ехидна
4. Королевский приют имени графа Тадеуса Оберона
Любовные романы:
любовно-фантастические романы
9.34
рейтинг книги
Мама из другого мира. Дела семейные и не только

Восход. Солнцев. Книга IX

Скабер Артемий
9. Голос Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Восход. Солнцев. Книга IX

Идущий в тени 3

Амврелий Марк
3. Идущий в тени
Фантастика:
боевая фантастика
6.36
рейтинг книги
Идущий в тени 3

С Новым Гадом

Юнина Наталья
Любовные романы:
современные любовные романы
эро литература
7.14
рейтинг книги
С Новым Гадом

Флеш Рояль

Тоцка Тала
Детективы:
триллеры
7.11
рейтинг книги
Флеш Рояль

Мастер Разума

Кронос Александр
1. Мастер Разума
Фантастика:
героическая фантастика
попаданцы
аниме
6.20
рейтинг книги
Мастер Разума

Неожиданный наследник

Яманов Александр
1. Царь Иоанн Кровавый
Приключения:
исторические приключения
5.00
рейтинг книги
Неожиданный наследник

Восход. Солнцев. Книга XI

Скабер Артемий
11. Голос Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Восход. Солнцев. Книга XI

Система Возвышения. (цикл 1-8) - Николай Раздоров

Раздоров Николай
Система Возвышения
Фантастика:
боевая фантастика
4.65
рейтинг книги
Система Возвышения. (цикл 1-8) - Николай Раздоров

Таблеточку, Ваше Темнейшество?

Алая Лира
Любовные романы:
любовно-фантастические романы
6.30
рейтинг книги
Таблеточку, Ваше Темнейшество?

Пенсия для морского дьявола

Чиркунов Игорь
1. Первый в касте бездны
Фантастика:
попаданцы
5.29
рейтинг книги
Пенсия для морского дьявола

Герой

Бубела Олег Николаевич
4. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.26
рейтинг книги
Герой