- •1 Основные понятия программного обеспечения Характеристики функциональных задач при постановке задач
- •2 Характеристика программного продукта. Основные характеристики программ, показатели качества пп. Дерево характеристик качества.
- •Программы
- •Программные продукты
- •3. Организация процесса разработки программ. Пример Характеристик основных этапов разработки программ.
- •3.1. Этапы создания программного продукта.
- •4 Основные цели структуризации программного продукта. Пример структурной схемы пп.
- •5 Проектирование интерфейса пользователя. Что определяется для управления диалоговыми процессами. Что выполняет описание сценария диалога, пример диалогового сценария и графического интерфейса.
- •6.Модульное программирование. Свойства программ-много модуля. Функциональная структура приложения.
- •Раздел 5 планирование работ по созданию программных продуктов
- •Тема 5.1. Структура разделения работ по созданию программного продукта
- •Тема 5.1.5 Составление временного графика выполнения программного проекта
- •7.1Тестирование программного продукта
- •1. Общая характеристика тестирования и его цикл
- •4. Тестирование документации
- •Раздел 8 Динамическая память.
- •Тема 8.1 Карта памяти – Куча. Виды указателей. Особенности объяв-ления данных динамической структуры. Пример.
- •9 Списковые структуры. Формирование списка. Пример.
4. Тестирование документации
Читая и анализируя документацию, тестировшик прежде всего уделяет внимание ее точности, полноте, ясности, простоте использования и тому, насколько она соответствует ПП. В ходе тестирования документации наверняка будут найдены проблемы по каждому из указанных критериев. Поэтому заранее следует запланировать многократное тестирование печатного руководства, интерактивной справки и других документов.
Тестировщик, работающий с документацией, отвечает за техническую точность каждого ее слова. Он обязан произвести самую тщательную проверку ее соответствия требованиям спецификации и поведению программы. Особо следует обращать внимание на сложные и запутанные места текста. Они могут отражать неудачно спроектированные элементы самой программы. Технический писатель обязан описать продукт таким, каким он является на самом деле, поэтому помочь устранить запутанные места может только изменение проекта. Настаивать на таких изменениях важно еще и потому, что, в конечном счете, они обеспечат не только простоту документирования продукта, но и легкость его использования.
Необходимо проверить, не пропущены ли в документации какие-нибудь функции продукта. Технические писатели опираются на спецификацию, собственные заметки и беседы с разработчиками. Разработчики стараются держать их в курсе дела, но иногда забывают сообщить о новых функциях, только что внесенных в программу. Поскольку тестировщики сталкиваются с этими функциями гораздо раньше технических писателей, стоит позаботиться, чтобы их описания попали в документацию. Кроме того, если определенная функция описана в руководстве, то это не значит, что она будет описана и в интерактивной справке. Вполне вероятно, что информация легко может потеряться.
Следует помнить, что тестировщик одинаково не имеет права требовать изменений как в руководстве к ПП, так и в самом ПП. Обязанность тестировшика — выявить проблему, а что с ней делать, решать не ему. В частности, у тестировщика нет никакого права требовать стилистических изменений текста. Он может предложить такие изменения, но технический писатель вправе оставить все как есть и не обязан доказывать тестировщику, что поступает правильно. Для взаимодействия с техническими писателями формальная система отслеживания проблем обычно не применяется. Большинство комментариев вносится прямо в копию руководства.
По договоренности с техническим писателем выбирается способ выделения в тексте правок и комментариев. Копии комментариев следует сохранять и проверять по ним очередные версии документации.
Раздел 8 Динамическая память.
Тема 8.1 Карта памяти – Куча. Виды указателей. Особенности объяв-ления данных динамической структуры. Пример.
Память – последовательность байтов пронумерованных от 0.
Номер соответствует адресу. С адресов кратных 16 начинаются сегменты – участки памяти размеров не более 65 536 байт, используемые для кода программы и данных.
Участок размером в 16 байт называют параграфом.
Потенциальный максимум размера адресной памяти равен 65536 * 16 байт, так как сегмент задаются номером начального параграфа, а это число типа Word.
Абсолютный адрес (Адрес)
состоит из Сегмента (номера параграфа) (ВА) и
Смещение – номера байта в пределах сегменте (BS)
(BA:BS)
Например : Var Number : Integer; т.е.даем указание компилятору на резервирование области памяти, на которую мы будем ссылаться по имени Number адрес по котором расположена переменная Number в памяти можно определить с помощью оператора @
P1:@Number; или через функцию P1:=@Number
Размер сегмента стека – 16384 байта. Увеличить его (вплоть до 64К) можно директивой ($M) см. Дальше Карту памяти или с помощью Элемента Memory подменю Compile.
Карта памяти. Куча.
Возьмем пример схемы 1: Uses M1,M2
Чем меньше памяти займут модули тем больше её остаётся для размещения данных.
Статические данные – это та часть памяти которая распределяется транслятором. И в основной программе, и в блоках можно запросить Динамически распределенную память (8 pn) под те или иные структуры, глобального ли локального характера.
ДРП – это вся свободная память, не занятая системными программами и сегментами называются также КУЧА.
По умолчанию минимальный размер кучи – 0, max – 655 360. Директиву $M<Размер стека>,<Минимум кучи>,<Максимум кучи> можно запретить уменьшение ДРП до 0 и задать другой максимум.
Сам TP занимает в памяти свыше 300К. Если нужно увеличить кучу выходных из TP перед запуском EXE – файла (перед этим надо получить EXE- файл при значении Disk опция Destination в подменю Compile)
Старшие адреса
До 64 К
До 64 К До 64 К До 64 К
До 64 К
256 байт |
Системные программы
|
Указатели
HeapEnd = 40955 40595 HeapPtr = 5195 21550 HeapOrg = 6263 2620 OvrHeapEnd
OvrHeapOrg
Sseg:Sptr = 5239 21596 Sseg:0000
Младшие адреса памяти. |
Ещё не распределенная память.
Динамически распределяемая область памяти; расширяется в сторону увеличения адресов |
||
Оверлейный буфер (создаётся тольков оверлейных программах) |
||
Сегмент стека; стек прирастает в сторону уменьшения адресов.
Свободная память стека. |
||
Сегмент данных основной программы; глобальные переменные и типизированные константы. |
||
Сегмент кода модуля System. |
||
Сегмент кода модуля М1 |
||
Сегмент кода модуля М2 |
||
Сегмент кода основной программы. |
||
Префикс основной программы. |
||
Турбо Паскаль. Системные программы |
Рисунок 21- Карта памяти
Указателем называют переменную значением которой является Адрес.
На карте памяти обозначены указатели
Начала Кучи Heap Org
оверлейного буфера OvrHeapOrg,
края занятой части кучи HeapPtr,
конца кучи HeapEnd,
Составляющие адреса Sseg и Sptr границы свободной части сегмента стека.
В начале работы программы это Сегмент кода программы (Сегмент данных) в смысле состоящей адреса.
Указатели не могут быть не введены, ни выведены.
Функция Seg(P^), Ofs(P^) возвращает составляющие Адреса, состоящие указателю P. Знак ^ надо читать как «указывает».
Получается смысл “Адрес того места памяти, куда указывает P”.
Составляющие адреса можно вводить и выводить.
Работа с динамическими структурами данных, распреде-ление памяти.
Особенности объявления данных динамической структуры.
Динамическая переменная не указывается явно в описаниях переменных и у нее нет имени. Для доступа к динамическим переменным предназначены переменные специального типа данных, Называемого ссылочным типом.
Указатели – разновидности данных, ссылочного типа.
В результате указатель будет обычной переменной, а переменная на которую он будет указывать динамической.
Var
P: ^Char P:*^Char P^:Char
адрес
‘*’
BeginP^: =‘*’;
…..
end;
Использование идентификатора указателя означает обращение к адресу ячейки памяти, на которую он указывает.
Чтобы обратиться к содержимому ячейки на которую указывает указатель требуется поставить символ ^.
Это операция называется – разыменованием.
Указательная переменная P может быть:
Содержать адрес какой – либо переменной 2n память под которую уже выделена
Адрес
P P^
Содержать специальный пустой адрес nil
Nil
P
3)Находится в неопределенном состоянии
?
P
?
4)Различие между состоянием nil и неопределенным состоянием
P1 P2 P1 P2
Nil
Nil
Nil
Nil
? ?
P1< >P2
P1=P2
На рисунке 22 представлены Простейшие действия с указателями
Рисунок 22 Простейшие действия с указателями
Задача 1. (Задание 6.3 Зубов стр.118)
Запишите программу которая выводит Сегмент (часть адреса) – начало её кода, начало данных и кучи, конца кучи, Сегмент границы свободной части кучи и стека.
Запустить программу из TP и выйдя из него
Program Ku;
Uses crt;
BEGIN
clrscr;
writeln('Функция CSeg и DSeg возвращает значение из регистра CS и DS...',CSeg,' ',DSeg);
writeln('Начало кучи ',Seg(HeapOrg^),' Конец кучи ',Seg(HeapEnd^));
writeln(Seg(HeapPtr),' Края занятые частью кучи');
writeln('Адрес границы свободной части сегмента стека ',SSeg);
readln;
END.
Использование абсолютных адресов.
Функция Seg (<Имя>) (Сегмент)
Ofs(<Имя>) (Сегмент)
Речь идёт о первом байте значения или коде.
Можно узнать где транслятор разместил блоки и переменные программы. Можно разместить переменную <Имя > по выбранному <Адресу> указав константные выражения путём обьявления
Var <Имя>:<Тип>Absolute<адрес>
Var Z:Byte Absolute $F0000:$FFFF;
В место адреса после Absolute можно записать имя другой переменой и произойдет совмещение.
Var A,B,C:Real;
D:Array[1..5] jf Real Absolute A; D[1]- A, D[2] – B, D[3] – C; транслятор выделяет для А,В,С, соединение 4- байтные участки памяти.
Имеются три глобальных перекрывающих массива Mem, MemW, MemL.
Элементы массива покрывают всю память имея тип Byte (массив MemL),
Для Mem и для элементов массивов MemW MemL в качестве индексов используются адреса (неномера).
Составляющие Адреса – это выражения типа Word.
Задача 2. Запишите программу с определением константы:
ConstX:Longint=2147483000;
и выводом соответствующих ей элементов массивов MemL запишите константы и MemW: Program Ku2;
Uses crt;
Const X: Longint=2147483000;
Bedin clrscr;
Writeln(MemL[seg(x):ofs(x)],’ ’,MemW[seg(x):ofs(x)]);
End.
Описание нетипизированных указателей.
Var <Список имен указателей> :Pointer
В первом случае не важен характер объекта ссылки указатель обозначает пункт памяти.
Описание типизированных указателей
2) Var <Список имен указателей >: ^ <имя базового типа>
Во втором случае
2.1) Type Vec=Array [1..5] of Real; Pnt=^Word;
Var S:^Byte; SS:^Vec; SSS:Pnt ( 3 переменных ссылочного типа )
В описании SS используется ранее описанный ссылочный тип Pnt.
2.2) Var T:^Array[1..5] of Real; TT:^Array[1..5] of Real тождественность типов T и TT транслятор не установит и Т:TT или TT:T невозможна Ситуация изменяется если определить для T и TT единый ссылочный тип
Type Pt=^Array[1..5] of Real
Var T,TT:Pt.
Указатели можно сравнивать на равенство (неравенство).
Указатели занимают 4 байта памяти (сегмент + смещение).
Имя сегмент Sg и Смещение Sm, значение указателя получают с помощью функции Ptr(Sg,Sm)
Операция @<Имя блока или переменная> возвращает указатель начала блока или поля переменной тот же результат функции Addr.
Для порождения динамических обьектов предназначена стандартная процедура NEW(A) где A – параметр ссылочного типа.
После работы процедуры NEW(A) переменная A получает значение ссылки на порожденный обьект.
Чтобы получить доступ к динамически выделенной памяти, необходимо написать “A^,
что означает “ идти по адресу хранящемуся в A^
Например
Progaram E2;
VAr x,y:^Integer;
…..
NEW(x); x^:=13; y:=x;
Writeln(y^);
Writeln(x^+20);
Сначала динамически порождается объект целого типа. Это означает, что выделяется место в памяти, но ничего туда не заносится.
Х - переменная ссылочного типа, ей присваивается адрес динамического объекта
X^:=13 заносит число 13 в динамическую переменную
Y- cссылочная переменная может содержать адрес с любого объекта целого типа поэтому Y:=X
Он заносится в переменную Y значение того же адреса, что храниться в переменных, первый оператор выводит 13, второй 33
1
Адрес
13
Адрес
Но при этом целочисленное значение хранящиеся в динамической переменой не изменяются .
Для уничтожения динамических объектов служит стандартная процедура DISPOSE(x)
где – x переменная ссылочного типа.
После окончания работы процедуры ссылочной переменной X присваивается значение Nil, а память занимаемая динамической переменной освобождается.
Списки. стр.98 Абрамов Нач.прог.
Program KU;
Uses crt;
Type pint:^integer;
Var i:Integer; p,g:pint;
Begin clrscr;
New(p); New(g) i:=5
p^:=7; g^:=p^-i; i:=i+1;
p^:=g^+I; g:=p;
Write(g^);
End;
1. Ситуация 2. После выполнения оператора New(p),New(g)
i:=5
i
5
i
p
p
g g^
g
- переменные i,p,g получили значения
3. Получили и некоторые 4.Теперь значения p и g
значения и переменные совпадают
p^,g^ и изменилось
значение i.
6
6
i i p^g^P^
p p
2
g g
Ответ 8.
То есть значение обеих переменных является ссылкой на одно и то же место в памяти. Место в памяти, ссылка на которое прежде являлась значением переменой g, теперь стало недоступным.
Это место в памяти называется “Мусор”.
Процедуры GetMem, FreMem.Переменный размер структур.
GetMem (<Указатель>,<Размер поля в байтах>) запрашивает поле указанного размера и в случае успеха возвращает ссылку на него –значение<Указателя>.
Он может быть типизированным и не типизированным.
FreMem (<Указатель>,<Размер в байтах>), освобождается поле, заданным <Указателем> возвращает память в кучу.
Эти процедуры дают способ построения структур с переменным числом компонентов.
Размер поля, выделенного с помощью процедуры New и GetMem, всегда доводится до кратного 8 (увеличивается, если не кратное) те начальные адреса сегментов ДРП так же кратны 8.
Пример: Создадим динамический массив из чисел типа Word, для проверки созданной структуры заполним массив числами 1,2 .. n , а затем выведем первый и последний элемент. Начальная строка программы позволяет легко перейти к элементам иного типа
Например, если они имеют тип Real, запишем в 1-й строке Type Tip = Real; . Type Tip = Word;
Const m = 65520 div SizeOf(Tip); {Предельное число элементов)
Type Vec = Array[1..m] of Tip;
Pt = ^ Vec; {Ссылочный тип с именем Pt}
Var ],n: Word; Ss: Pt; {Ss ~ типированный указатель}
BEGIN {Ниже записан ввод числа элементов динамического массива} Repeat Writeln('Вводите n'); Readln(n) Until (n>0) And (n<=m); GetMem ( Ss, n*SizeOf(Tip)); {Выделяется поле размером 2п}
For j:=1 to n do
Ss^ [0] := j; {Занесение значений 1, 2, ... , n)
Writeln (Ss^[1],' ', Ss^[n]); {Выводим 1-й и последний элементы/
FreeMem (Ss, n*SizeOf(Tip));
Readln;
END.
Взамен контроля значения п в цикле Repeat можно было бы дать переменной п тип 1..т; и перед вводом п включить директивой {$R+} контроль выхода из диапазона.
Сделав описание типа с именем Vec, мы не потратив ни одного лишнего байта, получаем широкий диапазон значений п, но фактически сводим на нет автоконтроль выхода индекса из диапазона 1..п, В самом деле, обращение к элементу SS^[j], когда n < j < 65520 div SizeOf(Tip), не будет воспринято как "криминал" даже в случае действия директивы ,{$R+h хотя элемента этого нет и вместо него нечаянно-негаданно обрабатывается или иная переменная, или вообще "пустота". Последствия непредсказуемы.
При использовании структур с переменным размером следует вводить в программе собственный контроль выхода из диапазона.