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

на главную

Жанры

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

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

Шрифт:

3.2. Выделение памяти

Четыре библиотечные функции образуют основу управления динамической памятью С Мы опишем сначала их, затем последуют описания двух системных вызовов, поверх которых построены эти библиотечные функции. Библиотечные функции С, в свою очередь, обычно используются для реализации других выделяющих память библиотечных функций и операторов C++

new
и
delete
.

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

3.2.1. Библиотечные вызовы:

malloc
,
calloc
,
realloc
,
free

Динамическую

память выделяют с помощью функций
malloc
или
calloc
. Эти функции возвращают указатели на выделенную память. Когда у вас есть блок памяти определенного первоначального размера, вы можете изменить его размер с помощью функции
realloc
. Динамическая память освобождается функцией
free
.

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

3.2.1.1. Исследование подробностей на языке С

Вот объявления функций из темы справки GNU/Linux malloc(3):

#include <stdlib.h> /* ISO С */

void *calloc(size_t nmemb, size_t size);

 /* Выделить и инициализировать нулями */

void *malloc(size_t size);

 /* Выделить без инициализации */

void free(void *ptr);

 /* Освободить память */

void *realloc(void *ptr, size_t size);

 /* Изменить размер выделенной памяти */

Функции выделения памяти возвращают тип

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

Тип

size_t
является беззнаковым целым типом, который представляет размер памяти. Он используется для динамического выделения памяти, и далее в книге мы увидим множество примеров его использования. На большинстве современных систем
size
_t является
unsigned long
, но лучше явно использовать
size_t
вместо простого целого типа
unsigned
.

Тип

ptrdiff_t
используется для вычисления адреса в арифметике указателей, как в случае вычисления указателя в массиве:

#define MAXBUF ...

char *p;

char buf[MAXBUF];

ptrdiff_t where;

p = buf;

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

 ...

 p += something;

 ...

 where = p - buf; /* какой у нас индекс? */

}

Заголовочный файл

<stdlib.h>
объявляет множество стандартных библиотечных
функций С и типов (таких, как
size_t
), он определяет также константу препроцессора
NULL
, которая представляет «нуль» или недействительный указатель. (Это нулевое значение, такое, как 0 или '
((void*)0)
'. Явное использование 0 относится к стилю С++; в С, однако,
NULL
является предпочтительным, мы находим его гораздо более читабельным для кода С.)

3.2.1.2. Начальное выделение памяти:

malloc

Сначала память выделяется с помощью

malloc
. Передаваемое функции значение является общим числом затребованных байтов. Возвращаемое значение является указателем на вновь выделенную область памяти или
NULL
, если память выделить невозможно. В последнем случае для обозначения ошибки будет установлен
errno
. (errno является специальной переменной, которую системные вызовы и библиотечные функции устанавливают для указания произошедшей ошибки. Она описывается в разделе 4.3 «Определение ошибок».) Например, предположим, что мы хотим выделить переменное число некоторых структур. Код выглядит примерно так:

struct coord { /* 3D координаты */

 int x, y, z;

} *coordinates;

unsigned int count; /* сколько нам нужно */

size_t amount; /* общий размер памяти */

/* ... как-нибудь определить нужное число... */

amount = count * sizeof(struct coord); /* сколько байт выделить */

coordinates = (struct coord*)malloc(amount); /* выделить память */

if (coordinates == NULL) {

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

}

/* ... использовать координаты... */

Представленные здесь шаги являются стереотипными. Порядок следующий:

1. Объявить указатель соответствующего типа для выделенной памяти.

2. Вычислить размер выделяемой памяти в байтах. Для этого нужно умножить число нужных объектов на размер каждого из них. Последний получается с помощью оператора С

sizeof
, который для этой цели и существует (наряду с другими). Таким образом, хотя размер определенной структуры среди различных компиляторов и архитектур может различаться,
sizeof
всегда возвращает верное значение, а исходный код остается правильным и переносимым.

При выделении массивов для строк символов или других данных типа

char
нет необходимости умножения на
sizeof(char)
, поскольку последнее по определению всегда равно 1. Но в любом случае это не повредит.

3. Выделить память с помощью

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

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

Кровь на эполетах

Дроздов Анатолий Федорович
3. Штуцер и тесак
Фантастика:
альтернативная история
7.60
рейтинг книги
Кровь на эполетах

Студиозус 2

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

Темный Патриарх Светлого Рода

Лисицин Евгений
1. Темный Патриарх Светлого Рода
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Темный Патриарх Светлого Рода

Изгой Проклятого Клана. Том 2

Пламенев Владимир
2. Изгой
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Изгой Проклятого Клана. Том 2

Приручитель женщин-монстров. Том 6

Дорничев Дмитрий
6. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 6

Бестужев. Служба Государевой Безопасности

Измайлов Сергей
1. Граф Бестужев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бестужев. Служба Государевой Безопасности

На границе империй. Том 10. Часть 2

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
5.00
рейтинг книги
На границе империй. Том 10. Часть 2

70 Рублей

Кожевников Павел
1. 70 Рублей
Фантастика:
фэнтези
боевая фантастика
попаданцы
постапокалипсис
6.00
рейтинг книги
70 Рублей

Ученик. Книга третья

Первухин Андрей Евгеньевич
3. Ученик
Фантастика:
фэнтези
7.64
рейтинг книги
Ученик. Книга третья

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Метатель

Тарасов Ник
1. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Метатель

Один на миллион. Трилогия

Земляной Андрей Борисович
Один на миллион
Фантастика:
боевая фантастика
8.95
рейтинг книги
Один на миллион. Трилогия

Завод: назад в СССР

Гуров Валерий Александрович
1. Завод
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Завод: назад в СССР

Треск штанов

Ланцов Михаил Алексеевич
6. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Треск штанов