Проблема осознанной деинсталляции хука возникает еще и потому что обычно указатель на хук передается на хранение вовне без знания того, кому он передается, поэтому, даже внутри финализатора не всегда можно определить, откуда этот хук должен быть деинсталлирован, если такая возможность вообще существует. Поэтому реализация финализатора не обеспечит бескровную возможность выгрузить модуль.
Иными словами, объект не может сам сообщить о невалидности своему владельцу.

Получается, что для проверки валидности всегда нужен промежуточный объект (возможно хранимый в объектном пуле, для эффективности).
Для критичных мест получается что-то типа:
## Код:
```
MODULE Abase;

   TYPE 
      A* = POINTER TO ABSTRACT RECORD END;
      
      (* всегда рядом с абстракцией, то есть, не выгрузится пока есть клиенты *)
      SafeA = POINTER TO RECORD (A0) 
         unsafe: A;
      END;
      
   PROCEDURE (a: A) Do*, NEW, ABSTRACT;
   
   PROCEDURE (a: SafeA) Do;
   BEGIN
      IF Valid(a.unsafe) THEN a.Do END
   END Do;
   
   PROCEDURE New*(): A;
      VAR a: SafeA;
   BEGIN
      NEW(a);
      a.unsafe:=dir.New();
      RETURN a
   END New;

END Abase.
```

Сработает ли финализатор объекта из модуля реализаций, который заякорен в базовом модуле? По идее - должен.
## Код:
```
MODULE Aimpl;
   
   TYPE
      HostA = POINTER TO RECORD (Abase.A) 
         host: WinApi.A;
      END;
   
   PROCEDURE (a: HostA) Do;
   BEGIN
      (* smth *)
   END Do;
   
   PROCEDURE (a: HostA) FINALIZE;
   BEGIN
      Free(a.host)
   END FINALIZE;
   
END Aimpl.
```

Для менее критичных случаев подойдет
## Код:
```
TYPE   
      Ref* = RECORD 
         target: ANYPTR;
      END;
      
   PROCEDURE (VAR r: Ref) Set*(x: ANYPTR), NEW;
   BEGIN
      r.target:=x;
   END Set;
   
   PROCEDURE (VAR r: Ref) This*(): ANYPTR, NEW;
      VAR ret: ANYPTR;
   BEGIN
      IF r.target#NIL THEN
         IF Valid(r.target) THEN ret:=r.target ELSE r.target:=NIL END;
      END;
      RETURN ret
   END This;
```
