Программирование на C и C++

Онлайн справочник программиста на C и C++

Динамическое выделение и указатели

У всех откомпилированных программ С при размещении в памяти можно выделить четыре области: код программы, глобальные данные, стек и куча. Куча - это область свободной памяти, управляемая функциями динамического выделения malloc() и free().

Функция malloc() выделяет память и возвращает указатель на начало выделенного блока. Функция free() возвращает ранее выделенную память в кучу для повторного использования. Ниже показаны прототипы функций malloc() и free():

void *malloc(size_t число_байт);
void free(void *p);

Обе функции используют заголовочный файл stdlib.h. Здесь число_число - это число требуемых байт. Если недостаточно свободной памяти для выполнения запроса, malloc() возвращает NULL. Тип size_t определен в stdlib.h и является беззнаковым целым типом, способным хранить размер памяти, выделяемой при одном вызове malloc(). Важно, что free() должна вызываться только с корректным, ранее выделенным указателем, иначе структура кучи может быть повреждена, что может привести к краху программы.

фрагмент кода, показанный ниже, выделяет 25 байт памяти:

char *р;
р = (char *) malloc(25);

После присвоения р указывает на первый из 25 выделенных байт. Оператор принудительного преобразования char* не нужен в С, но необходим в С++. В С, если не используется преобразование типов с malloc(), то тип указателя автоматически преобразуется к типу, аналогичному типу переменной, стоящей слева оператора присваивания. В С++ такое неявное преобразование указателей не разрешается. Хотя в С это и не нужно, использование преобразований типов позволяет программам С компилироваться с помощью С++. Ниже показан фрагмент кода, выделяющий место для 50 целых чисел. Он использует sizeof для обеспечения переносимости:

int *р;
р = (int *) malloc(50*sizeof (int));

Поскольку куча не бесконечна, при выделении памяти необходимо проверять значение, возвращаемое malloc(), чтобы убедиться, что оно не нулевое. Использование нулевого указателя может привести к зависанию компьютера. Ниже показан корректный способ выделения памяти и тестирования на корректность указателя:

int *р;
if ((р = (int *) malloc (100) )==NULL)
{
printf("Out of memory.\n");
exit (1);
}

Макроопределение NULL находится в stdlib.h. Конечно, можно использовать другой обработчик ошибок вместо exit(). Самое главное - не использовать указатель р, если он нулевой.

Следует включать заголовочный файл stdlib.h в начало всех файлов, использующих функции malloc() и free(), поскольку он содержит их прототипы.