Читайте также:
|
|
Расширение:
1) кода – новый модуль изменяет работу процедур существующих модулей;
2) данных – новый модуль добавляет к существующим объектам новые свойства;
Расширение кода.
1) Постановка задачи: Существуют модули A, B, C. В и С импортируют А. В В и С нужно изменить работу модуля А, если А изменять нельзя, В и С ничего не знают друг о друге.
2) Решения:
А) процедурные переменные – традиционное решение. В ООП процедурные переменные скрываются в таблицах виртуальных методов.
MODULE A
Procedure Insert* (S:string); * – public-процедура
Var InsertEvent*: PROCEDURE (S: string)
MODULE B
import A
Procedure OnInsert(s: string)
Begin End;
Проблемы: 1) затраты на дизайн; (register/unregister для поддержки некоторых обработчиков, возможость отметы вставки, синхронизация при доступе из разных потоков)
2) разрыв контекста (beforeInsert, afterInsert. Перехватываются обе процедуры. А если несколько потоков? Разные процедуры должны работать с 1м контекстом)
3) нарушение инварианта var InsertInProgress (B.Insert – true, A.Insert – false)
В случае исключения переменная InsertInProgress остается в неправильном состоянии. Нарушение инварианта – следствие нарушения контектса.
Скрытая рекурсия.
Insert* (s: string)
Begin
InsertIvent(S) – м.б. неявная рекурсия
End;
Рекурсия м.б. недопустима, но компилятор обладает недостаточной информацией. A.Insert(s).
5) Выгрузка модулей. Если модуль нужно выгрузить, возможно ли дать ОС команду «выгрузить модуль»? Нет, т.к. он может иметь ссылки с других модулей. Сама система не может удалить модель, не имеет права его выбросить.
Решение всех указанных проблем – переопределение процедур.
MODULE A; MODULE B
PROCEDURE Insert* (S:string); IMPORT A;
BEGIN PROCEDURE A.Insert+ (S:string);
… BEGIN
END; …
… BASE(s);
END A. …
END;
END B.
Реализация: 1) перенастройка адресов (при загрузке модуля реализации В. Старое значение нужно сохранить в переменной);
2) вызов через процедурную переменную – для всех процедур модуля объявляется неявная переменная, модуль переопределяет процедуры;
3) процедура-переходник. Делается вызов процедуры-переходника, которая вызовет функцию через процедурную переменную, переходник сделает jmp. Перехват – изменение переменных, через которые делается вызов;
Замена кода процедуры по месту. В 1х инструкциях сделать jmp на свою процедуру.
NET компиляция происходит в промежуточный язык (полностью лишен недостатков). За счет представления программы в промежуточном языке можно осуществить перехват.
Минусы:
1) сначала нужно пройтись по всему коду – затраты времени;
2) все вызовы косвенные – потеря производительности;
Дата добавления: 2015-11-16; просмотров: 56 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Microsoft Visual Studio | | | Всегда есть потеря на jmp; |