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

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

Жанры

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
значения к типу переменной, которой это значение присваивается. В С этого не требуется (хотя компилятор может выдать предупреждение). Мы настоятельно рекомендуем всегда приводить возвращаемое значение.

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

Старый, но крепкий

Крынов Макс
1. Культивация без насилия
Фантастика:
рпг
уся
попаданцы
5.00
рейтинг книги
Старый, но крепкий

Хозяин Теней 7

Петров Максим Николаевич
7. Безбожник
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Хозяин Теней 7

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

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

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

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

Наномашины, первоклашка! Том 4

Новиков Николай Васильевич
4. Чего смотришь? Иди книгу читай
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наномашины, первоклашка! Том 4

Сапер

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

Наследие Маозари 2

Панежин Евгений
2. Наследие Маозари
Фантастика:
попаданцы
рпг
аниме
5.00
рейтинг книги
Наследие Маозари 2

Эйзенштейн

Шкловский Виктор Борисович
Жизнь в искусстве
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Эйзенштейн

Хозяин Стужи 8

Петров Максим Николаевич
8. Злой Лед
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Хозяин Стужи 8

Запасная дочь

Зика Натаэль
Фантастика:
фэнтези
6.40
рейтинг книги
Запасная дочь

Страж Тысячемирья

Земляной Андрей Борисович
5. Страж
Фантастика:
боевая фантастика
альтернативная история
фэнтези
5.00
рейтинг книги
Страж Тысячемирья

Матабар VIII

Клеванский Кирилл Сергеевич
8. Матабар
Проза:
магический реализм
5.00
рейтинг книги
Матабар VIII

Кодекс Крови. Книга ХVI

Борзых М.
16. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХVI

Хозяин Стужи 3

Петров Максим Николаевич
3. Злой Лед
Фантастика:
аниме
фэнтези
попаданцы
7.00
рейтинг книги
Хозяин Стужи 3