Скачиваний:
62
Добавлен:
04.03.2014
Размер:
46.59 Кб
Скачать

Динамическое распределение памяти

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

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

Для прикладной реализации механизма динамического распределения памяти в системе программирования C предусмотрены функции malloc, calloc, free и realloc. Программный интерфейс этих функций обеспечивает заголовочный файл <stdlib.h>, где декларированы типы их аргументов и кода возврата. Некоторые известные реализации системы программирования C предоставляют эквивалентную спецификацию в файлах заголовков <alloc.h> и <malloc.h>. Объектный код функций динамического распределения памяти сосредоточен в стандартной библиотеке объектных модулей системы программирования C.

Функция malloc позволяет динамически распределить блок памяти заданного размера. Спецификация формата ее вызова имеет вид:

Void* malloc(unsigned size);

Функция malloc реализует просмотр свободных блоков из кучи, чтобы найти сплошное пространство памяти, размер которого в байтах не меньше, чем задано параметром size. В случае успеха она возвращает адреса первого свободного блока памяти достаточного размера. Полученный адрес следует использовать для доступа к содержимому выделенного блока памяти после явного преобразования типа. Если требуемый объем памяти не может быть выделен, или значение параметра size равно 0, функция malloc возвращает нулевой указатель NULL.

Функция calloc обеспечивает динамическое распределение памяти кучи под массив элементов. Спецификация формата ее вызова имеет вид:

Void* calloc(unsigned num, unsigned size);

Через аргументы num и size в функцию calloc передаются требуемое число элементов и размер каждого элемента массива. Таким образом, суммарный объем памяти, выделенный при обращении к функции calloc, равен (num*size) байтов. Все элементы выделенного массива автоматически инициализируются нулевыми значениями. При успешном завершении функция calloc возвращает адрес динамически распределенного массива. Если требуемый объем памяти не может быть выделен, или значения аргументов равны 0, функция calloc возвращает нулевой указатель NULL.

Использование функций malloc и calloc иллюстрирует пример динамического распределения памяти для узла списка. В нем предполагается, что каждый узел списка специфицирует программная структура struct Node, декларация которой имеет следующий формат:

struct Node {

char* data; /* информационное поле */

struct Node* next; /* адресное поле */

}; /* Node */

Адресное поле next этой структуры обеспечивает связь со следующим узлом списка. Информационное поле data должно адресовать символьную строку данных узла. При формировании нового узла списка необходимо динамически распределить память под структуру struct Node и для хранения символьной строки данных. Требуемое распределение памяти обеспечивает следующий исходный код прикладной функции alloc.

/* Динамическое распределение узла списка */

struct Node* alloc(char* str, unsigned len) {

struct Node* ptr; /* Указатель на структуру узла списка */

unsigned size; /* Размер структуры узла списка */

int count = 0; /* Счетчик символов в строке данных */

/* Вычислить объем структуры узла списка */

size = sizeof(struct Node);

/* Распределить память для узла списка */

if((ptr = (struct Node *) malloc(size)) == NULL)

return(NULL);

/* Распределить память для информационного поля узла списка */

if((ptr->data = (char* ) calloc((len + 1), 1)) == NULL)

count = len;

/* Копирование данных в информационное поле узла списка */

while(count < len)

ptr->data[count++] = *str++;

/* Возврат адреса распределенного узла списка */

return(ptr);

} /* alloc */

При вызове в функцию alloc следует передать адрес и длину строки данных, которые обозначают аргументы str и len, соответственно. В случае успеха распределения памяти функция alloc возвращает адрес нового узла списка. Его можно использовать, чтобы, например, добавить узел в конец текущего списка или вставить после заданного узла списка.

Эффективность динамического распределения памяти определяет не только способность выделить точно такой объем памяти, какой нужен в программе, но и возможность освобождать распределенную память, когда информация в ней перестает быть необходима. Чтобы освобождать динамически выделенную память, в системе программирования C предусмотрена функция free. Формат ее вызова имеет вид:

Соседние файлы в папке Инфа - бесценно