Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lec_12_pres.doc
Скачиваний:
3
Добавлен:
05.12.2018
Размер:
246.27 Кб
Скачать

5. Особливості звертання до динамічної пам'яті через функції Borland c

Як вже зазначалось, молодші та старші моделі розподілу пам'яті використовують різну динамічну пам'ять (див. табл. 1). Зокрема, модель Tiny може використовувати тільки внутрішню динамічну пам'ять, тобто незайняту кодом і даними область у межах єдиного програмного сегмента.

Моделі Small і Medium теж мають внутрішню динамічну пам'ять, розташовану в межах сегмента даних. Крім цього вони можуть використовувати зовнішню динамічну пам'ять, яка займає вільну на даний момент частину оперативної пам'яті з адресного простору MS DOS (див. рис. 1).

Старші моделі Compact, Large і Huge не мають внутрішньої динамічної пам'яті, вони можуть використовувати тільки зовнішню heap-область (див. рис. 2).

Наявність двох видів динамічної пам'яті (внутрішньої та зовнішньої для малих моделей і тільки зовнішньої для старших моделей розподілу пам'яті) зумовлює особливості організації бібліотечних функцій Borland C, які реалізують звертання до динамічної пам'яті. Бібліотека Borland C містить також ряд додаткових функцій, які дають змогу визначати обсяг незайнятої динамічної пам'яті, здійснювати покроковий контроль пам'яті, перевіряти звільнені попередньо блоки пам'яті або змінювати обсяг блоку тощо. Прототипи цих функцій записані в заголовному файлі <alloc.h>.

У разі компіляції програми для молодших моделей розподілу пам'яті, стандартні бібліотечні функції malloc (), calloc (), realloc () та free () використовують внутрішню динамічну пам'ять. Сумарний обсяг усіх ділянок виділених у динамічній пам'яті цими функціями, не може перевищувати обсяг сегменту (64 Кбайт). Параметр обсягу пам'яті в цих функціях має тип size_t (тобто unsigned int). Всі функції працюють з короткими (near) вказівниками.

Якщо ж у програмі, що компілюється для моделі пам'яті Small або Medium, для збереження даних заплановано використовувати зовнішню динамічну пам'ять, то треба скористатись відповідними функціями з префіксом far-: farmalloc (), farcalloc (), farrealloc () та farfree (). Параметр обсягу пам'яті в far-функціях має тип unsigned long, що дає змогу виділяти динамічні ділянки, обсяг яких перевищує 64 Кбайт. Перелічені функції працюють з вказівниками довгого (far) формату. Наприклад, прототип функції farmalloc (), яка є аналогом функції malloc (), але призначена для роботи зі зовнішньою динамічною пам'яттю, оголошено так:

void far* farmalloc (unsigned long memsize);

У програмах, розрахованих на молодші моделі розподілу пам'яті, вказівники, що використовуються для звертання до зовнішньої динамічної пам'яті, мають бути обов'язково оголошені з модифікаторами far або huge. Наприклад:

double far* darr;

darr= (double far*) farcalloc(1000, sizeof(double));

Вказівник darr отримає адресу першого байта ділянки, розташованої у зовнішній динамічній пам'яті, в яку можна записати масив із 1000 дійсних чисел.

Якщо створюється динамічний масив, обсяг якого більший ніж 64 Кбайт (обсяг сегмента пам'яті), то для коректної адресації елементів такого масиву слід застосовувати huge-вказівники, щоб уникнути помилок адресної арифметики, властивих far-вказівникам у випадках міжсегментних переходів.

Для старших моделей розподілу пам'яті Compact, Large і Huge, які за замовчуванням працюють з довгими вказівниками і використовують тільки зовнішню динамічну пам'ять, можна застосовувати як стандартні функції без префікса far-, так і відповідні функції з цим префіксом.

Обидві функції malloc () і farmalloc (), а також всі інші пари відповідних функцій у разі старших моделей виконують однакові дії та повертають однакове значення. Різниця між ними полягає тільки в обсязі ділянки, яка може бути виділена або звільнена функцією у зовнішній динамічній пам'яті.

Для стандартних функцій обсяг не може перевищувати 64 Кбайт, а для функцій з префіксом far- обмеження накладає лише обсяг вільної динамічної пам'яті.

В <alloc.h> оголошено також ряд функцій, призначених для контролю незайнятої та звільненої частини пам'яті. Зокрема, обсяг вільної внутрішньої та зовнішньої динамічної пам'яті повертають функції coreleft ():

unsigned coreleft(void); /* для внутрішньої ДП */

unsigned long farcoreleft(void); /* для зовнішньої ДП */

unsigned long coreleft(void); /* для старших моделей */

Властивості функції coreleft (), а також функцій виділення і звільнення динамічної пам'яті у разі молодших і старших моделей пам'яті Borland C ілюструють результати реалізації поданої нижче демонстраційної програми.

У програмі оголошено два вказівники pmdl та pfar, перший з яких отримує формат за замовчуванням відповідно до встановленої моделі пам'яті, а другий оголошено явно як huge-вказівник. Вказівник pmdl, який набуває адреси динамічної ділянки обсягом 10000 байтів, використовується для роботи з функціями без префікса far.

Відповідно в молодших моделях він буде пов'язаний з внутрішньою, а в старших - зі зовнішньою динамічною пам'яттю. Вказівник pfar призначений для роботи зі зовнішньою динамічною пам'яттю, він адресує ділянку, обсяг якої становитиме 150000 байтів. Допоміжний масив arr оголошено як глобальний, він займає 50000 байтів у сегменті даних програми.

/*********************************************************************************/

/* Звертання до динамічної пам'яті у разі малих і великих */

/* моделей розподілу пам'яті системи програмування Borland C */

/*********************************************************************************/

#include <stdio.h>

#include <alloc.h>

char arr[50000]; /* глобальний масив */

int main (void)

{

char* pmdl; /* вказівник за замовчуванням */

char huge* pfar; /* дальній вказівник */

printf("\n\t Вільна динамічна пам\'ять (у байтах): \n"

"1) перед виділенням пам'яті:\n");

printf("внутрішня\зовнішня (за замовчуванням) - %61u",

(long)coreleft());

printf(" зовнішня - %61u", farcoreleft());

pmdl =(char *)malloc( 10000 ) ; /* виділення пам'яті *

pfar =(char huge *) farmalloc (150000) ;

printf("\n 2) після виділення пам'яті:\n");

printf("внутрішня/зовнішня (за замовчуванням) - %61u",

(long)coreleft() );

printf(" зовнішня - %61u", farcoreleft());

free(pmdl); farfree(pfar); /* звільнення пам'яті *

printf("\n 3) після звільнення пам\'яті:\n");

printf("внутрішня/зовнішня (за замовчуванням) - %61u",

(long)coreleft());

printf(" зовнішня - %61u", farcoreleft());

return 0; }

Приклад виконання програми для моделі пам'яті Small:

Вільна динамічна пам'ять (у байтах)

1) перед виділенням пам'яті:

внутрішня/зовнішня (за замовчуванням) - 13488, зовнішня – 532304

2) після виділення пам'яті:

внутрішня/зовнішня (за замовчуванням) - 3488, зовнішня – 382288

3) після звільнення пам'яті:

внутрішня/зовнішня (за замовчуванням) - 13488, зовнішня – 532304

Приклад виконання для моделі пам'яті Large:

Вільна динамічна пам'ять (у байтах)

1) перед виділенням пам'яті:

внутрішня/зовнішня (за замовчуванням) - 542032, зовнішня – 542032

2) після виділення пам'яті:

внутрішня/зовнішня (за замовчуванням) - 382000, зовнішня – 382000

3) після звільнення пам'яті:

внутрішня/зовнішня (за замовчуванням) - 542032, зовнішня - 542032

Із наведених результатів видно, що для моделі пам'яті Small функції без префікса far- працюють з внутрішньою динамічною пам'яттю, яка займає вільний простір сегмента даних програми, де зберігається масив arr. Функції з префіксом far- програмують зовнішню динамічну пам'ять.

Коли ж програму відкомпільовано для моделі пам'яті Large, то використовується тільки зовнішня динамічна пам'ять, в якій для потреб програми функції malloc () та farmalloc () виділяють дві ділянки, сумарний обсяг яких становить 10000+150000=160000 байтів.

38/38

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]