Правила области видимости для обобщенных ссылочных типов
В целях обеспечения надежности, на использование обобщенных ссылочных типов накладываются некоторые дополнительные ограничения.
Так, область видимости косвенно доступного объекта, на который будет ссылаться значение переменной обобщенного ссылочного типа T, не должна быть глубже чем область видимости переменной обобщенного ссылочного типа T.
Это подразумевает, что следующий пример - не корректен, и, следовательно, будет отвергнут компилятором:
procedure Illegal is -- внешняя область видимости описаний
type Integer_Access is access all Integer; Integer_Ptr : Integer_Access; begin . . . declare -- внутренняя область видимости описаний Integer_Variable : aliased Integer; begin Integer_Ptr := Integer_Variable'Access; -- это не корректно!!! end; -- завершение области видимости -- переменной Integer_Variable Integer_Ptr.all := Integer_Ptr.all + 1; -- сюрприз! -- переменная Integer_Variable -- больше не существует! end Illegal; -- завершение области видимости -- для Integer_Access |
Смысл примера заключается в следующем.
Во внутреннем блоке, переменной IA ссылочного типа Integer_Access
присваивается значение которое ссылается на переменную IVar.
При завершении внутреннего блока, переменная IVar прекращает свое существование.
Следовательно, в следующей инструкции присваивания, переменная IA
ссылается на не существующую переменную.
Такая ситуация известна как "проблема висячих указателей".
Такое ограничение выглядит достаточно строго, но оно гарантирует, что любой объект на который могут ссылаться значения типа Integer_Access
будет существовать на протяжении всего времени существования переменных типа Integer_Access.
В частности, если тип Integer_Access описан на уровне библиотеки, то область видимости Integer_Access определяется всей программой, а это значит, что с типом Integer_Access могут быть использованы только те переменные, которые описаны на уровне библиотеки.
Бывают случаи когда необходимо нарушить строгость данного ограничения.
Тогда, для получения ссылочного значения, вместо атрибута 'Access
можно использовать атрибут 'Unchecked_Access, который позволяет получить ссылочное значение без осуществления проверки правил доступа:
procedure Legal_But_Stupid is type Integer_Access is access all Integer; IA : Integer_Access; begin . . . declare IVar : aliased Integer; begin IA := IVar'Unchecked_Access; -- это не надежно!!! end; IA.all := IA.all + 1; -- теперь это будет только ВАША ошибка!!! end Legal_But_Stupid; |
Это подразумевает, что при его использовании вы должны быть полностью уверены в своих действиях.
Еще одним способом, который позволяет обходить эти ограничения, является описание обобщенных ссылочных типов внутри настраиваемых модулей.
Идея такого подхода основана на том, что область видимости для типа который описан внутри настраиваемого модуля будет ограничена областью видимости места конкретизации этого настраиваемого модуля.