Банк рефератов содержит более 364 тысяч рефератов, курсовых и дипломных работ, шпаргалок и докладов по различным дисциплинам: истории, психологии, экономике, менеджменту, философии, праву, экологии. А также изложения, сочинения по литературе, отчеты по практике, топики по английскому.
Полнотекстовый поиск
Всего работ:
364150
Теги названий
Разделы
Авиация и космонавтика (304)
Административное право (123)
Арбитражный процесс (23)
Архитектура (113)
Астрология (4)
Астрономия (4814)
Банковское дело (5227)
Безопасность жизнедеятельности (2616)
Биографии (3423)
Биология (4214)
Биология и химия (1518)
Биржевое дело (68)
Ботаника и сельское хоз-во (2836)
Бухгалтерский учет и аудит (8269)
Валютные отношения (50)
Ветеринария (50)
Военная кафедра (762)
ГДЗ (2)
География (5275)
Геодезия (30)
Геология (1222)
Геополитика (43)
Государство и право (20403)
Гражданское право и процесс (465)
Делопроизводство (19)
Деньги и кредит (108)
ЕГЭ (173)
Естествознание (96)
Журналистика (899)
ЗНО (54)
Зоология (34)
Издательское дело и полиграфия (476)
Инвестиции (106)
Иностранный язык (62792)
Информатика (3562)
Информатика, программирование (6444)
Исторические личности (2165)
История (21320)
История техники (766)
Кибернетика (64)
Коммуникации и связь (3145)
Компьютерные науки (60)
Косметология (17)
Краеведение и этнография (588)
Краткое содержание произведений (1000)
Криминалистика (106)
Криминология (48)
Криптология (3)
Кулинария (1167)
Культура и искусство (8485)
Культурология (537)
Литература : зарубежная (2044)
Литература и русский язык (11657)
Логика (532)
Логистика (21)
Маркетинг (7985)
Математика (3721)
Медицина, здоровье (10549)
Медицинские науки (88)
Международное публичное право (58)
Международное частное право (36)
Международные отношения (2257)
Менеджмент (12491)
Металлургия (91)
Москвоведение (797)
Музыка (1338)
Муниципальное право (24)
Налоги, налогообложение (214)
Наука и техника (1141)
Начертательная геометрия (3)
Оккультизм и уфология (8)
Остальные рефераты (21697)
Педагогика (7850)
Политология (3801)
Право (682)
Право, юриспруденция (2881)
Предпринимательство (475)
Прикладные науки (1)
Промышленность, производство (7100)
Психология (8694)
психология, педагогика (4121)
Радиоэлектроника (443)
Реклама (952)
Религия и мифология (2967)
Риторика (23)
Сексология (748)
Социология (4876)
Статистика (95)
Страхование (107)
Строительные науки (7)
Строительство (2004)
Схемотехника (15)
Таможенная система (663)
Теория государства и права (240)
Теория организации (39)
Теплотехника (25)
Технология (624)
Товароведение (16)
Транспорт (2652)
Трудовое право (136)
Туризм (90)
Уголовное право и процесс (406)
Управление (95)
Управленческие науки (24)
Физика (3463)
Физкультура и спорт (4482)
Философия (7216)
Финансовые науки (4592)
Финансы (5386)
Фотография (3)
Химия (2244)
Хозяйственное право (23)
Цифровые устройства (29)
Экологическое право (35)
Экология (4517)
Экономика (20645)
Экономико-математическое моделирование (666)
Экономическая география (119)
Экономическая теория (2573)
Этика (889)
Юриспруденция (288)
Языковедение (148)
Языкознание, филология (1140)

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

Название: Динамическое распределение памяти
Раздел: Рефераты по информатике, программированию
Тип: лабораторная работа Добавлен 21:07:12 06 июля 2009 Похожие работы
Просмотров: 205 Комментариев: 2 Оценило: 0 человек Средний балл: 0 Оценка: неизвестно     Скачать

ДИНАМИЧЕСКОЕ РАСПРЕДЕЛЕНИЕ ПАМЯТИ

Введение

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

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

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

Студенты должны научиться исследованию программ, используя режим отладки. Они должны убедиться в пользе отладчика не только при поиске ошибок, но и на стадии разработки программы.

Для обязательного выполнения рекомендуются задания 1, 6, 7, 10. Задание 4 можно использовать в качестве курсовой работы.

1. Модели памяти

Виды моделей

Моделью памяти называется набор опций компилятора, определяющий размер и структуру оперативной памяти, предоставляемой программе при ее выполнении.

В BC++2.0 существуют несколько видов моделей памяти: tiny, small, medium, compact, large, huge. Программа может быть откомпилирована в любой из этих моделей, если установить соответствующий флажок в Opions-Compiler-Code Generation-Model. При этом используются различные наборы встроенных библиотек и создаются различные obj-файлы. Например, для модели large в директории Lib имеются файлы C0l.obj, Cl.lib, Mathl.lib и другие. Возможная ошибка на этапе линковки (“Не могу найти файл Сol.obj”) вызвана неполной версией пакета и неверным выбором модели.

Модели памяти не являются частью языка Си, а зависят от используемой оболочки.

Когда программа загружается в ОЗУ для выполнения, ей отводится определенное место, в котором можно выделить несколько областей: область кода (ОК); область данных, глобальных и статических переменных(ОД); стек; куча (heap или динамическая память).

Таблица 1

вид модели памяти максимальный размер
Область кода область данных стек куча взаимное расположение
tiny 64К 64К 64К 64К все области в одном сегменте
small 64К 64К 64К 64К ОД,стек и куча в одном сегменте
medium 64К 64К 64К различные сегменты
compact 64К 64К различные сегменты
large 64К 64К различные сегменты
huge 64К 64К различные сегменты

Модель Large

Модели памяти устроены по-разному. Рассмотрим расположение областей памяти в модели large.


Рис. 1

PSP представляет собой префикс программного сегмента, занимает 256 байт и помещается перед исполняемыми файлами при их загрузке в память. Он содержит переменные, используемые MS-DOS для управления программой, а также место для переноса данных окружения.

Область кода содержит машинные коды функций программы. Функции, присоединенные к exe-файлу на стадии линковки, размещаются вне области кода.

Область данных содержит глобальные и статические переменные, строковые константы.

В стеке размещаются локальные переменные, параметры, передаваемые функциям, и ряд других данных. Как правило, стек растет сверху вниз, занимая пульсирующую непрерывную область. В случае переполнения стека происходит его "налезание" стека на область данных и выдается соответствующее сообщение. Проверка стека увеличивает время работы программы и ее можно отключить в Options-Entry/Exit Code Generation-Stack options-Test stack overflow.

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

Сегментные регистры

Сегмент - это область памяти размером не более 64K, созданная для хранения кода, данных или стека. Сегменты всегда выровнены на границу параграфа (16 байт), поэтому их адрес получается умножением сегментного регистра на 0x10=16.

В некоторых моделях памяти код может занимать больше 64K. Области кода, данных и стек начинаются с параграфов с номерами содержащимися, соответственно, в регистрах CS, DS, SS.

В режиме отладчика можно просматривать содержимое регистров в окне Window-Register. При повторных запусках программы сегментные регистры могут быть различны.

Значения сегментных регистров, кроме того, хранятся в глобальных псевпеременных, имеющих то же название с подчеркиванием: _CS, _DS и т.д. Их можно использовать в программе, например, распечатать, учитывая, что псевпеременные являются шестнадцатиричными беззнаковыми числами printf(”CS =%x”, _CS);

Просмотр переменных

В режиме отладчика можно определить адреса и значения переменных, находящихся в своей области видимости, с помощью Alt-F4. Например.

- Для переменной i, описанной как inti; i = 5; окно просмотра имеет вид

-

8FAC:FFF4 5(0x0005)
Int

Здесь указан адрес переменной в формате [сегмент]:[смещение]. Полный адрес переменной равен 8FAC0+FFF4=9FAB4

- Для переменной ptri, описанной как

int i = 4, *ptri;

ptri = &i;

окно просмотра имеет вид

8FAC:FFF2 п Ds:FFF4
[0] 4(0x0004)
Int *

Здесь указаны: адрес самой переменной ptri, равный 8FAC:FFF2; значение этой переменной Ds:FFF4; а также содержимое ячейки по адресу Ds:FFF4, т.е. значение i. Для того, чтобы узнать содержимое ячеек, окружающих переменную i, нужно воспользоваться комбинацией клавиш Alt-I, ввести начальный индекс (Starting index) и число ячеек (Count). Если, например, введены числа -5 и 15, то можно в приведенном выше окне можно просмотреть элементы массива ptri[-5], ptri[-4],…,ptri[10].

Объекты, размещенные в куче, не имеют имени. Поэтому просматривать динамические объекты можно только предыдущим способом, т.е. по адресу.

Абсолютные адреса и размеры областей памяти в модели large

Область кода занимает часть ОЗУ, содержащую параграфы с номерами от CS до DS-1. Таким образом, размер области кода равен (DS-CS)*0x10.

Область данных занимает часть ОЗУ, содержащую параграфы с номерами от DS SS-1. Таким образом, размер области данных равен (SS-DS)*0x10.

Стек начинается с параграфа SS, но растет справа налево, от старших адресов к младшим. Новые данные помещаются в стек в вершине стека. Смещение вершины стека относительно SS равно SP. Таким образом, полный адрес вершины равен SS:SP. В начале программы стек пуст, поэтому он занимает ячейки с адресами от SS*0x10 до SS*0x10, а размер стека равен SP.

На кучу остается память с адреса SS*0x10+SP по 0xA0000=640K.

Реальный размер кучи зависит от способа запуска программы. Сама оболочка Borland C++2.0 занимает в ОЗУ порядка 200K, и для программы, выполнямой из оболочки, остается немного места - примерно 300K. Если же программа запускается из командной строки DOS или из Norton Commander, то куча будет значительно больше.

При выполнении программы из оболочки и в отладчике под кучу отводится еще меньше места, поэтому ее размер в этом случае разрешается устанавливать вручную с помощью опции Options-Debugger-Program heap size.

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

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

void *malloc(size_t size);

Выделяет блок ДП размером size байт. Здесь size_t совпадает с типом unsignedint. Таким образом, блок не превосходит размер в 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 байт, то фраза уместилась бы в первом параграфе, и ошибки бы не произошло. Источник хорошо скрытой логической ошибки!

4. Дополнительные фунции ДРП

Определение размера свободной области кучи

unsignedlongcoreleft(void);

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

Блочное выделение памяти

void *calloc(size_tNItems, size_tSizeOfItem);

Выделяет и обнуляет память для Nitems фрагментов по SizeOfItem байт каждый. Размер фрагмента не превосходит 64K, но общий объем памяти может превышать 64K. В случае неудачи возвращается NULL.

Проверка целостности кучи

int heapcheck(void);

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

Просмотр блоков кучи

int heapwalk(struct heapinfo *hi);

Просматривает кучу блок за блоком. Предполагается, что сбоев в куче нет, для этого используйте heapcheck. Фнукция получает указатель на структуру heapinfo. При первом вызове, установите hi.ptr в 0. Функция устанавливает этот указатель на адрес очередного блока. Другие поля структуры size, in_useпозволяют определить размер блока в байтах и его занятость. Для очередного блока функция вернет _HEAPOK, для последнего блока _HEAPEND.

Пример 3. Занятые и свободные блоки.

#include <stdio.h>

#include <alloc.h>

#define NUM_PTRS 4

#define NUM_BYTES 20

int main(void)

{

struct heapinfo hi;

char *array[ NUM_PTRS ];

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

array[ i ] = (char *)malloc(NUM_BYTES);

for(i = 0; i < NUM_PTRS; i += 2)

free(array[ i ]);

hi.ptr = NULL;

printf(" РазмерСтатус\n");

printf(" ---- ------\n");

while(heapwalk(&hi) == _HEAPOK)

{

printf("%7u ", hi.size);

printf("%s\n",(hi.in_use?"используется": "свободен"));

}

return 0;

}

В результате будет напечатано

Размер Статус
528 Используется
32 Свободен
32 Используется
32 Свободен
32 Используется

Инициализация свободных блоков кучи

int heapfillfree(unsigned int fillvalue);

Заполняет байты свободных блоков кучи константным значением fillvalue.

Проверка свободных блоков кучи

intheapcheckfree(unsignedintfillvalue);

Проверяет байты свободных блоков кучи на их равенство константному значению fillvalue.

Функции группы far.

В моделях памяти, где куча не превышает 64K, можно использовать память вне этой области - дальнюю кучу. Для работы с дальней кучей имеются свои версии функций, c префиксом far.

5. Лабораторные задания

Области памяти

Для следующей программы укажите значения сегментных регистров. Укажите абсолютные адреса и размеры в байтах области кода; области данных, глобальных и статических переменных; стека; кучи. Модель памяти large. Определите в отладчике адреса и размещение по областям переменных: main; Privet; Dlit в функции main; i и Dlit в функции Privet; printf.

void Privet(int sound); // прототипфункции Privet

main(){

int Dlit = 5;

Privet(Dlit); //вызовфункции Privet

}

void Privet(int Dlit) { // заголовокфункции Privet

{

printf("Привет!\n");

printf("С добрым утром!");

for(int i = 0; i<Dlit; i++) //печатаетпервые Dlit

printf("%c", i); // символов ascii-таблицы

}

Исследование менеджера ДРП

Выделите динамическую память для трех данных типа char. Адреса сохраните в переменных char *x, *y, *z. Определите в отладчике адреса *x, *y, *z. Убедитесь, что для кажго из однобайтовых данных будет отведено в куче 16 байт,т.е. целый параграф.

Односвязный список менеджера

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

Новый менеджер

Язык Си не пускает дефрагментации ДП. Напишите свой менеджер, содержащий функции mymalloc, myfree, mydefrag.

Сумма свободных блоков

Определите суммарный объем "дырок" в куче, образовавшихся после освобождения блоков.

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

Выделите память под 20 переменных типа int. Заполните их случайными целыми числами из интервала от -3 7. Выведите их на экран.

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

Выделите память под двумерный массив 3х5 типа float. Заполните их случайными вещественными числами из интервала от -3.6 7.4 с шагом 0.1. Выведите их на экран в виде таблицы. Массив представьте в виде строки.

Структура для матрицы переменных размерностей.

Создайте структуру для хранения информации о матрице переменных размерностей. Рассмотрите две возможности

StructMatr1{ intm, n; int *ptr;};

Struct Matr2{ int m, n; int **ptr;};

Напишитефункции

int DinMatr1(Matr1 *matr);

intDinMatr2(Matr2 *matr);

для корректного выделения памяти под массив

Умножение матриц

Напишите функцию умножения матриц переменных размерностей.

Ввод чисел

С клавиатуры вводятся натуральные числа. Признак конца ввода - число 0. Сохраняйте числа в куче. По окончании ввода выдайте числа на экран.

Список строк

Создайте односвязный список для хранения текстовых строк, вводимых с клавиатуры. Выведите их на экран в обратном порядке.

Норма матрицы

Октаэдрической нормой квадратной матрицы А, nxn, называется число ÷÷A÷÷ = max{÷a1 j ÷+÷a2 j ÷+ …+÷anj ÷: j=1,…n}. Напишитефункцию для вычисления нормы матрицы.Размеры матрицы произвольный.

Наибольшая по размеру квадратная матрица.

Найдите наибольший размер N, для которого в куче можно выделить в памяти место для квадратной матрицы NxN чисел типа float. Получите результат при запуске программы из командной строки DOS и из оболочки BC.

Модификация функции coreleft.

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

Свободна ли куча?

Напишите функцию определяющую, свободна ли куча.

Работа с файлом.

Запишите динамическую матрицу в файл, прочитайте из файла и распечатайте.

Библиографический список

1. Керниган Б, Ритчи Д. Язык программирования Си. М.: Фин. и стат., 1992.

2. Керниган Б, Ритчи Д. Язык программирования Си. Задачи по курсу Си. М.: Фин.и стат., 1985.

3. Уинер Р. Язык ТурбоСи. М.:Мир, 1991.

4. Хинт К. Си без проблем. Руководство пользователя. М.: Бином, 1997.

Трофимов С.П. Программирование в Си. Организация ввод-вывода // Метод. указания, Екатеринбург, Изд-во УГТУ, 1998, 20 с.

Оценить/Добавить комментарий
Имя
Оценка
Комментарии:
Где скачать еще рефератов? Здесь: letsdoit777.blogspot.com
Евгений06:47:43 19 марта 2016
Кто еще хочет зарабатывать от 9000 рублей в день "Чистых Денег"? Узнайте как: business1777.blogspot.com ! Cпециально для студентов!
19:53:34 28 ноября 2015

Работы, похожие на Лабораторная работа: Динамическое распределение памяти

Назад
Меню
Главная
Рефераты
Благодарности
Опрос
Станете ли вы заказывать работу за деньги, если не найдете ее в Интернете?

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



Результаты(150051)
Комментарии (1830)
Copyright © 2005-2016 BestReferat.ru bestreferat@mail.ru       реклама на сайте

Рейтинг@Mail.ru