Реферат: Программирование ориентированное на объекты
├───────────────────┤ ─┐─┘
│ │ │
├───────────────────┤ │
│ │ > Свободный фрагмент, ранее
├───────────────────┤ │ использованный под
│ │ │ объект Т2^
└───────────────────┘ ─┘
Иллюстрация построена для момента обработки запроса NEW(M2). В этот момент времени в динамической памяти имеются два свободных фрагмента общим объемом шесть слов, которых достаточно для выполнения запроса на выделение элемента хранения под объект М2^ (т.е. для объекта, на котоpый будет указывать M2), однако фрагментация не позволяет системе выделить память под объект М2^.
Система управления динамической памятью ведет специальный список свободных фpагментов - пул памяти. При возвращении какого-либо элемента хранения, используемого в прикладной программе, в пул свободной памяти может быть реализовано "склеивание" соседних свободных фpагментов в один фpагмент большего объема. Например, если в предыдущей программе изменить последовательность обращений к динамической памяти на приведенную ниже, то описанного выше отказа по памяти не произойдет:
BEGIN NEW(T1);...NEW(T2);...NEW(M1);...
DISPOSE(T1);...DISPOSE(T2);... NEW(M2);...
Здесь при обработке запроса NEW(M2) в пуле динамической памяти будет находиться один свободный фрагмент объема шесть слов, образованный "склеиванием" элементов Т1^ и T2^, выполненным при обработке запроса DISPOSE(T2). В общем случае вопросы эффективной реализации управления динамической памятью, обеспечивающей минимум отказов при ограниченном объеме, составляют отдельную проблему. Здесь мы только заметим, что с организацией выделения "первого подходящего" фрагмента памяти в программировании связывают такие термины как "хип" или "куча", относящиеся скорее к профессиональному жаргону, чем к научно-методической терминологии. Тем не менее эти термины довольно образно характеризуют принципы организации динамической памяти.
Организация корректной последовательности запросов связана, кроме того, как минимум еще с двумя проблемами. На том же жаргоне их называют проблемы "висячих ссылок" и "мусора", а определяют они две стороны одной и той же ошибки, заключающейся в некорректной работе с указателями. Следующий фрагмент программы иллюстрирует возникновение таких ошибок (тип "Треугольник" описан выше).
VAR T1, T2:Треугольник;
BEGIN NEW(T1);...T2:=T1;...
DISPOSE(T1); (* T2-"висячая ссылка" *)
............
NEW(T1);...NEW(T2);...
T1:=T2; (* Остался "мусор" *)
Из этого примера понятно, что "висячая ссылка" - это указатель прикладной программы, указывающий на свободный фрагмент динамической памяти. Поскольку этот фрагмент может быть выделен системой по какому-либо запросу другой прикладной программе, Т2 может открыть доступ к "чужим" данным и "разрешить" их интерпретацию как треугольника. Последствия такой интерпретации в общем случае непредсказуемы. Заметим, что "висячая" ссылка и "пустая" ссылка (имеющая значение NIL, см. pазд.III) являются совершенно разными понятиями. "Мусор" - это занятый фрагмент динамической памяти, к которому в прикладной программе потерян доступ. В приведенном примере мусором оказался старый треугольник Т1^, на который указывал Т1 до передвижки (установки на Т2). Этот мусор неустраним: программист не имеет к нему доступа, а система управления "считает" мусор занятым фрагментом памяти.
Объединяет эти два вида ошибок одно общее обстоятельство: они не обнаруживаются исполнительной средой. Идентифицировать подобные ошибки можно только путем тщательной проверки и отладки программы. И, наконец, по своим возможным влияниям на работу программы мусор гораздо "безобиднее" висячей ссылки. Он фактически приводит только к увеличенному расходу памяти, в то время как висячая ссылка способна при определенных условиях полностью парализовать процесс выполнения программы. В сложных системах "цена" висячей ссылки может оказаться очень высокой.
Использование автоматической памяти связано с созданием / уничтожением специальных элементов хранения, связанных с активными объектами - действиями или процедурами. Любая процедура тpебует для выполнения собственной индивидуальной локальной среды. Подобную среду образуют локальные переменные, объявленные в процедуре, формальные параметры, элемент хранения адреса возврата в процедуру, т.е. набор объектов, обеспечивающих выполнение действий, связанных с процедурой. Необходимость в локальной среде возникает только в момент вызова процедуры - момент интерпретации объекта процедурного типа. После завершения такой интерпретации необходимость в локальной среде исчезает. Таким образом, время жизни локальной среды ограничивается временем отработки программы, в которой она описана. Соответственно запрос на создание локальной среды связан с вызовом процедуры, а запрос на уничтожение - с окончанием фазы активности объекта (оператор RETURN или END в теле процедуры). Например:
VAR W1, W2: PROC;
PROCEDURE Работа_1;
VAR A: INTEGER;... BEGIN... W2;...
END Работа_1;
PROCEDURE Работа_2;
VAR A: INTEGER;... BEGIN... W2;...
END Работа_2;
BEGIN... W1:=Работа_1;... W2:=Работа_2;... W1;...
В этом фрагменте описаны два активных объекта процедурного типа PROC = PROCEDURE(): W1 и W2 и две процедуры без параметров: Работа_1 и Работа_2, которые могут использоваться как константы типа PROC. Интерпретация (активизация) W1 приведет к вызову Работы_1 и созданию локальной среды (содержащей переменную А). В процессе выполнения Работы_1 производится активизация объекта W2 и соответственно создание локальной среды для Работы_2. В любой текущий момент времени в системе могут быть активны несколько объектов. (В этом примере активизация W1 приводит к активизации W2, затем они оба остаются в активном состоянии и затем теряют свою активность в обратной последовательности: сначала пассивируется W2, затем W1). Последовательность активации и пассивации связана с вложенностью вызовов процедур, соответственно управление автоматической памятью основывается на использовании стека - структуры, поддерживающей такую вложенность. Ниже для этого фрагмента приведена иллюстрация распределения автоматической памяти, существующего в течение совместной активности объектов W1 и W2.
┌─ ┌───────────────────┐ ─┐
│ │ Переменная А │ │
│ ├───────────────────┤ > Локальная среда
│ │ Адрес возврата │ │ для W1
Занятое прост- < ├───────────────────┤ ─┤
ранство │ │ Переменная А │ │
│ ├───────────────────┤ > Локальная среда
│ │ Адрес возврата │ │ для W2
Вершина ──> └─ │───────────────────┤ ─┤
стека │ │ │
автоматической │ │ │
памяти │ │ │ Свободное
│ │ > пространство
Пассивация │ │ │ памяти
│ ^ │ │ │
│ │ │ │ │
│ │ │ │ │
v │ └───────────────────┘ ─┘
Активация
При активации каждого нового объекта вершина стека "опускается вниз" на величину, определяемую размерами локальной среды этого объекта,- при его пассивации вершина стека "поднимается вверх". С использованием автоматической памяти связаны две основные проблемы: рекурсии и множественности ассоциаций.
Рекурсия - механизм, позволяющий объекту совершать самоактивац-ию. Например, по схеме:
W1-->W1 (прямая рекурсия)
или W1-->W2 ...-->W1 (косвенная рекурсия).
Прямая рекурсия связана с непосредственной повторной (вложенной) активацией, а косвенная - с опосредованной (причем число посредников в схеме W1-->...-->W1 может быть произвольным). Использование рекурсии напрямую связано с размерами рабочего пространства автоматической памяти. Использование рекурсивных активаций объектов, с одной стороны, позволяет иметь очень лаконичные и емкие по содержанию программы, с другой стороны, в рекурсивных схемах (особенно в косвенной рекурсии) возрастает вероятность появления трудно идентифицируемых ошибок.
Множественность ассоциаций заключается в том, что в классе автоматической памяти могут быть одновременно размещены несколько одноименных объектов, имеющих в общем случае различные значения и относящиеся к разным активностям одного и того же или опять-таки разных объектов. В приведенном примере существуют два одноименных объекта: переменная А, связанная (ассоциированная) с активностью W1, и переменная А, ассоциированная с активностью объекта W2. В соответствии с принципом стека система упpавления автоматической памятью всегда pассматpивает в качестве активной последнюю созданную ассоциацию (самую "ближнюю" к вершине стека автоматической памяти). Возникновение множественности ассоциаций обусловлено только использованием в прикладных программах одноименных переменных с различной областью действия (областью видимости). Если уж использование таких переменных и является необходимым (в чем всегда стоит усомниться), то при их интерпретации следует помнить о множественности ассоциаций.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄А___Б___v_Г___ Д___q_U___ Г___m_╜___ ╛___h_╤___ ¤___e_└___ ╟___b_е__ ┬________ ____Z___________________@___
____@____@_________ -___x_о___ ├___s_ч___ ■___n_Ф___ й___i_з__ │__d_└__ ╨____w"__ Ы"__Z_B#__ __________________________________B#__C#__t_j#__ k#__m_r#__ s#__f_а#__ б#____Ў#__ ў#__X_∙#__ ·#__Q_Н%__ w"__ Ы"_______Ї______Ї______Ї______Ї______Ї______Ї
Н%__О%__t_с&__ т&__m_='__ >'__f_P'__ Q'____0(__ 1(__X_3(__ 4(__Q_q(__ w"__ Ы"_______Ї______Ї______Ї______Ї______Ї______Ї
q(__(__v_к(__ ┤(__q_╗*__ ╩*__l_/+__ N+__g_S+__ T+__`_я+__ _,__[__,__ 5,__V__0__ __________________Ї____________________
_0__*0__v_51__ X1__q_Q9__ b9__n__;__ у;__k_O<__ T<__f_У<__ Я<__a_Y=__ v=__\_OA__ _______________________________________
OA___A__x_yA__ ИA__u_▒B__ ╛B__p_ЕC__ ЩC__k_▀C__ ьC__f_TD__ eD__a_УD__ жD__\_3J__ _______________________________________
3J__CJ__v_~J__ ЮJ__q_WK__ sK__l_ёL__ ўL__g_VN__ gN__b_hN__ iN____"O__ 2O__Z_+T__ _______________________________________
+T__;T__v_<T__q_╥U__ ╘U__l_┘X__ сX__g_╢\__ ╧\__b_Va__ ka__]_Ъb__ Ыb__V_3c__ +T__ ________
______________________________3c__5c__t_Уc__ Фc__m__f__ _f__f__g__ _g__a_▀g__ щg__^_ak__ ik__Y_jk__V_╪k__ +T__ ________________________
______
______
╪k__┘k__t_ l__ #l__o_/m__ 0m__h_╓p__ ·p__c_]q__ nq__a_Чq__ │q____├q__ Zr__]_░t__ Вu__Z_____7_7_7___________
___________
_Вu__pv__ zv__v_
w__ 1w__q_╫x__ яx__l_нy__ ├y__g_|z__ Иz__d_┼{__ ▄{__a_F~__ b~__^_BД__ __________________________________BД__DД__y_dД__ eД__w_ЭД__ ЯД__u_┴Д__ ├Д__s_уД__ фД__q__Е__ _Е__o_>Е__ @Е__m_`Е__ aЕ__k_ПЕ__ СЕ__i_____7_7_7_7_7_7_7_7_7_СЕ__ШЕ__ нЕ__y_├Е__ ┼Е__w_хЕ__ цЕ__u__Ж__ _Ж__s_ЭЗ__ ║З__n__Й__ Й__i_zЙ__ МЙ__d_YЛ__ ПЕ__ СЕ__________________7_7_7_7_YЛ__jЛ__v_ Л__ _М__q_┘М__ уМ__l_шМ__ яМ__g_шН__ ЄН__b_UО__ aО__]__Т__ _Т__V__Т__ YЛ______
______________________________
_Т___Т__t_эТ__r_мЧ__ ╦Ч__p_╪Ч__ ┘Ч__n_єЧ__ √Ч__l__Ш__ 4Ш__j_6Ш__ `Ш__h_bШ__ eШ__f_gШ__ КШ__d______7_7_7_7_7_7_7________
_КШ__МШ__ еШ__y_жШ__ оШ__w_╗Ш__ ┌Ш__u_█Ш__ ▀Ш__s_уШ__ _Щ__q_#Щ__ MЩ__o_OЩ__ RЩ__m__Щ__ ЙЩ__k_НЩ__ _7_7__7_7_7_7_7_7_7_7_НЩ__╖Щ__y_╣Щ__ ╝Щ__w_═Щ__ ўЩ__u__Ъ__ 2Ъ__s_4Ъ__ ^Ъ__q_█Ы__ эЫ__l_╫Э__ 'Ю__j_-Ю__ .Ю__h_6Ю__ 7Ю__f__7_7_7______7_7_7_7_7_7Ю__HЮ__ IЮ__y_RЮ__ SЮ__w_]Ю__ ^Ю__u_цЮ__ чЮ__s_ыЮ__ ЇЮ__q_¤Ю__ Я__o__Я__ _Я__m__Я__ XЯ__k_ZЯ__ _7_7__7_7_7_7_7_7_7_7_ZЯ__ХЯ__y_ЧЯ__ ╥Я__w_╘Я__ _а__u__а__ Hа__s_Jа__ Ба__q_ъл__ _м__l_
▒__ ╧▒__i_b┤__ n┤__f_S╢__ ZЯ__ ____________7_7_7_7_7_S╢___╢__v_"╣__ A╣__q_t╣__ П╣__l_p╝__ ╝__g_у┼__ х┼__`_╞__ _╞__Y__╞__ _╞__R_b┤________
______
______
_____________________╞___╞__ _╞__t_У╨__ ж╨__o_Я╪__ ╗╪__j_u▌__ Л▌__e_╬▌__ _▐__`_Y▀__ }▀__[_ф__ "ф__X_______________________________________
"ф__Aх__ [х__x_Qц__ mц__s_нц__ ┬ц__n_╪ш__ тш__i_шш__ Єш__d_#щ__ :щ____Bщ__ Pщ__Z__ы__ ___________________________________ы__&ы__v_Оы__ еы__q_бь__ вь__o_▒ь__ █ь__m_ э__ Pё__k_~ё__f_zў__d_вў____\___]__ __ _ы__ ____7_6____7_6____7_7_7__________
_ __ __v_\