2. Основные функции ДРП

  Выделение памяти

void *malloc(size_t size);

Выделяет блок ДП размером size байт. Здесь size_t совпадает с типом unsigned int. Таким образом, блок не превосходит размер в 64K. В случае отсутствия непрерывного блока заказанной длины, возвращается NULL.

Пример 1. Выделение массива для 1000 чисел типа float.

main() {

float *ptrf;

if((ptrf =(float *) malloc(1000 * sizeof(float)) == NULL)

printf("\nОшибка при выделении памяти!");

}

Освобождение памяти

void free(void *block);

Освобождает блок ДП, начинающийся с адреса block. Этот адрес должен находится в заголовке ранее выделенного блока (см. п.3). В противном случае, будет освобожден случайный блок и возникнет логическая ошибка. Динамические переменные не освобождаются автоматически при выходе из области действия и, таким образом, засоряют кучу.

Перевыделение памяти

void *realloc(void *block, size_t size);

Изменяет размер блока, на который указывает block. Новый размер блока будет равен size. Старая информация сохраняется. При нехватке свободных байт блок будет перемещен в новое место с одновременным копированием информации. Функция возвращает адрес нового блока, не изменяя переменную block.

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

main() {

float **A;

int n=5, n=10;

A = (float **)malloc(m * sizeof(float *));

if(A == NULL)

{

printf("\nОшибка при выделении памяти под массив указателей!");

exit(1);

}

for (int i=0; i< m; i++)

{

A[i] = (float *)malloc(n * sizeof(float));

if(A[i] == NULL)

{

printf("\nОшибка памяти под%d-ую строку!", i);

for(int j=0; j< i; j++)

free(A[j]);

free(A);

exit(2);

}

//…….

for(i=0; i< m; i++)

free(A[i]);

free(A);

}

 

3. Менеджер ДРП

Управлением ДП занимается специальный фрагмент кода, вызываемый в функциях ДРП. Он называется менеджером ДП. Мы исследуем работу менеджера в модели памяти large. В других моделях менеджер устроен по-другому.

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

Выделяемый блок памяти имеет вид

2 2 14 16 ….. 16

В заголовке находятся:

¾  длина блока в параграфах (2 байта),

¾  сегментный адрес предыдущего блока (2 байта),

¾  далее идут данные. Адрес начала данных и возвращается функциями ДРП.

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

Таким образом, зная адрес последнего занятого блока, можно определить длину, адрес и статус остальных блоков. Рассмотрим программу

main(){

char *block1=(char *)malloc(100);

char *block2=(char *)malloc(110);

char *block3=(char *)malloc(120);

free(block2);

}

Выполняя ее в отладчике, увидим, что до освобождения второго блока куча будет иметь вид (конкретные адреса будут другими!)

0х0007

0х90EF 0x0008 0x910F …. 0x0008 0x9116
Block1 Block2 Block3

Рис. 2

После выполнения оператора free(block2) куча будет иметь вид

0х0007

0х90EF 0x0008 0x0000 …. 0x0008 0x9116
Block1 Block2 Block3

Рис. 3

Замечание 1. Особенность динамических символьных строк.

Рассмотрим фрагмент кода, создающий динамическую строку.

main()

{

char *str; // ячейка str находится в стеке

str = (char *)malloc(13);

strcpy(str, "Hello,World!");

// строка Hello,World! помещается в кучу

}

Строка "Hello,World!" реально состоит из 13 символов, так как кроме самих символов содержит 0 - признак конца строки. Поэтому, если выделить только 12 элементов

Str = (char *)malloc(12),

то признак конца строки "залезет" на заголовок следующего блока ДП и изменит длину этого блока. Если бы длина строки была меньше 12 байт, то фраза уместилась бы в первом параграфе, и ошибки бы не произошло. Источник хорошо скрытой логической ошибки!

 


Информация о работе «Динамическое распределение памяти»
Раздел: Информатика, программирование
Количество знаков с пробелами: 17156
Количество таблиц: 9
Количество изображений: 1

Похожие работы

Скачать
46448
0
0

... до тех пор, пока во время счета не выполнится вход в блок, и котором описан массив. При входе в блок вычисляются границы массива и производится обращение  к программе распределения памяти для массивов. Здесь же вносится в информационный вектор необходимая информация. Какая информация заносится в информационный вектор? Для предложенной выше n-мерной схемы нам как минимум нужны ...

Скачать
48910
4
3

... .) В системах, в которых страницы инструкций (в противоположность страницам данных) являются реентерабельными, бит изменения никогда не устанавливается. 2. Разработка алгоритма управления оперативной памятью Ниже приведён алгоритм управления оперативной памятью в системе Linux. В основе всего лежат страницы памяти. В ядре они описываются структурой mem_map_t. typedef struct page { /* ...

Скачать
80963
2
5

... производительность 1600 Мбайт/с на двухбайтной шине данных при частоте 400 МГц. Стандарт DRDRAM поддержан множеством производителей микросхем и модулей памяти, он претендует на роль основного высокопроизводительного стандарта для памяти компьютеров любого размера. Подсистема памяти (ОЗУ) DRDRAM состоит из контроллера памяти, канала и собственно микросхем памяти. По сравнению с DDR SDRAM при той ...

Скачать
22335
4
0

... . Несет информацию об адресе текущего элемента однонаправленного динамического списка. q – указатель на структуру news. Несет информацию об адресе последнего созданного элемента однонаправленного динамического списка. news *un,*p,*q; i – переменная типа int. Несет информацию о количестве элементов однонаправленного динамического списка. int i; 4 2) Локальные переменные процедуры ...

0 комментариев


Наверх