ДИНАМИЧЕСКОЕ РАСПРЕДЕЛЕНИЕ ПАМЯТИ
Целью данной работы является выработка навыков использования динамической памяти, приучение к осознанному выбору подходящей модели памяти при компиляции программы.
Динамическое распределение памяти предоставляет программисту большие возможности при обращении к ресурсам памяти в процессе выполнения программы, и корректная работа приложения в существенной степени зависит от правильного обращения к соответствующим функциям.
Для выполнения заданий по этой теме студенты должны уметь работать в пошаговом отладчике, изображать схематичное расположение памяти при работе с указателями.
Студенты должны научиться исследованию программ, используя режим отладки. Они должны убедиться в пользе отладчика не только при поиске ошибок, но и на стадии разработки программы.
Для обязательного выполнения рекомендуются задания 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 | 1М | 64К | 64К | 64К | различные сегменты |
compact | 1М | 64К | 64К | 1М | различные сегменты |
large | 1М | 64К | 64К | 1М | различные сегменты |
huge | 1М | 64К | 64К | 1М | различные сегменты |
Модели памяти устроены по-разному. Рассмотрим расположение областей памяти в модели 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, описанной как int i; 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.
... до тех пор, пока во время счета не выполнится вход в блок, и котором описан массив. При входе в блок вычисляются границы массива и производится обращение к программе распределения памяти для массивов. Здесь же вносится в информационный вектор необходимая информация. Какая информация заносится в информационный вектор? Для предложенной выше n-мерной схемы нам как минимум нужны ...
... .) В системах, в которых страницы инструкций (в противоположность страницам данных) являются реентерабельными, бит изменения никогда не устанавливается. 2. Разработка алгоритма управления оперативной памятью Ниже приведён алгоритм управления оперативной памятью в системе Linux. В основе всего лежат страницы памяти. В ядре они описываются структурой mem_map_t. typedef struct page { /* ...
... производительность 1600 Мбайт/с на двухбайтной шине данных при частоте 400 МГц. Стандарт DRDRAM поддержан множеством производителей микросхем и модулей памяти, он претендует на роль основного высокопроизводительного стандарта для памяти компьютеров любого размера. Подсистема памяти (ОЗУ) DRDRAM состоит из контроллера памяти, канала и собственно микросхем памяти. По сравнению с DDR SDRAM при той ...
... . Несет информацию об адресе текущего элемента однонаправленного динамического списка. q – указатель на структуру news. Несет информацию об адресе последнего созданного элемента однонаправленного динамического списка. news *un,*p,*q; i – переменная типа int. Несет информацию о количестве элементов однонаправленного динамического списка. int i; 4 2) Локальные переменные процедуры ...
0 комментариев