Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 6004.doc
Скачиваний:
21
Добавлен:
30.04.2022
Размер:
1.29 Mб
Скачать

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

Для сегментированных моделей предусмотрено динамическое выделение памяти из ближнего (near) или дальнего (far) пулов. Функции для динамического распределения или перераспределения памяти определены в стандарте ANSI и включены практически во все библиотеки систем программирования на С. Прототипы функций для распределения памяти описаны в заголовочном файле <alloc.Н> (еще и в <malloc.Н>, <memory.Н> и т.п.).

Чтобы выделить блок памяти, используют функцию:

void *malloc(int size);

Параметром этой функции является запрашиваемое количество байт основной памяти. Эта функция возвращает адрес на начало выделенной динамической области.

Например:

int *p = (int*) malloc (1024);

- запpашивается область в 1К для хранения целых данных. float *p = (float*) malloc (1024);

- запpашивается область в 1К для хранения данных вещественного типа.

void *calloc(int items, int size_item);

- позволяет выделить заданное количество объектов указанного типа.

Передаются количество объектов и протяженность одного объекта.

При выделении памяти все пространство обнуляется.

Например:

int *p = (int*) calloc(256, sizeof(int));

- выделение памяти под 256 объектов длиной sizeof(int).

void *realloc (void *addr, int size); - перераспределение памяти. Первый параметр содержит адрес существующей области, второй параметр - новый размер этой области. Если изменение размера может быть выполнено, функция возвращает указатель на новую область.

Все эти функции в случае аварийного завершения возвращают нулевой указатель, т.е. NULL.

Для освобождения памяти используется функция

void free (void *adr);

которой передается адрес освобождаемой области.

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

2.5.3.Динамическое распределение памяти в windows nt

При программировании под MS Windows 3.х можно создать динамически распределенные области в локальном и глобальном пулах. Локальный пул выделяется каждому процессу, действующему в системе, а глобальный пул является общим для всех процессов. Выделение памяти из локального пула - LocalAlloc, выделение памяти из глобального пула - GlobalAlloc. Данные функции возвращают идентификатор выделенной области, т.е. некоторый номер, под которым эта область зарегистрирована в ОС. Чтобы получить зарегистрированную область в пользование, выполняют функцию GlobalLock, которая возвращает указатель. Снимается фиксация с помощью функции GlobalUnLock. GlobalFree - освободить ранее зарезервированную память.

В ОС WINDOWS 95 и WINDOWS NT нет разделения на локальные и глобальные пулы, поскольку адресные пространства всех приложений разделены. Каждое приложение работает в своем виртуальном адресном пространстве. Приложению по умолчанию выделяется один стандартный пул равный 1М и при необходимости приложение может создавать произвольное количество динамических пулов.

Ранее рассмотренные функции типа malloc, GlobalAlloc и т.п. позволяют выделять память из стандартного пула.

В программном интерфейсе Win32 API имеется несколько функций для работы с пулами. Всем функциям, используемым для распределения памяти, передается идентификатор пула, который имеет тип HANDLE. Для получения идентификатора стандартного пула существует функция: GetProcessНeap (void); которая возвращает данный идентификатор.

Для создания динамического пула применяется функция: HANDLE НeapСreate (DWORD flOptions,

DWORD dwInitialSize,

DWORD dwMaximumSize);

Тип DWORD соответствует unsigned long.

Первый параметр - флаги. Допустимы следующие сочетания: HEAP_GENERATE_EXEPTIONS - генерировать исключение при аварийном завершении; HEAP_NO_SERIALIZE - не выполнять блокировку одновременного обращения к пулу нескольких задач одного процесса. Сочетание этих флагов может быть обеспечено операцией логического сложения (дизъюнкцией).

Второй параметр - начальная длина пула;

Третий параметр - максимальная протяженность пула (если неизвестна, то = 0).

Функция разрушения динамического пула:

BOOL НeapDestroy (НANDLE ННeap);

Ей передается идентификатор пула, а возвращается логическое значение.

Получение блока памяти в пуле:

LPVOID НeapAlloc (НANDLE ННeap,

DWORD dwFlags,

DWORD dwBytes);

1 параметр - идентификатор пула;

2 параметр - рассмотренные ранее флаги и HEAP_ZERO_MEMORY, который позволяет обнулить выделенное пространство;

3 параметр - протяженность блока памяти.

Функция возвращает указатель на выделенную область памяти (LPVOID - дальний указатель на тип void: void far*).

Изменение протяженности ранее выделенного пространства:

LPVOID НeapRealloc (НANDLE ННeap,

DWORD dwFlags,

LPVOID lpMem,

DWORD dwBytes);

2 параметр - флаги. Используются все предыдущие + HEAP_REALLOC_IN_PLACE_ONLY (не изменять начальный адрес области);

3 параметр - адрес исходного блока;

4 параметр - новая протяженность.

Если нет ошибок, возвращается указатель на область нового размера.

Чтобы определить размер пула используется следующая функция:

DWORD НeapSize (НANDLE ННeap,

DWORD dwFlags,

LPVOID lpMem);

значения параметров флагов могут быть "0" или HEAP_NO_SERIALIZE.

Освобождение выделенного блока:

BOOL НeapFree(НANDLE ННeap,

DWORD dwFlags,

LPVOID lpMem);

значение флагов те же.