Плохая ссылка на объект уже освобожден - PullRequest
6 голосов
/ 22 сентября 2008

Есть ли способ убедиться, что у нас есть полезная ссылка на объект, т. Е. Быть уверенным, что он еще не освобожден, оставив эту ненулевую ссылку свисающей.

Ответы [ 7 ]

6 голосов
/ 22 сентября 2008

Если вы используете FastMM4 в качестве диспетчера памяти, вы можете проверить, что класс не TFreeObject .
Или, в более стандартном случае, используйте подпрограмму, которая проверит, что ваш объект является тем, о чем он говорит, путем проверки класса VMT .

В течение некоторого времени были такие функции ValidateObj (Рэй Лишнер и Халвард Вассботн: http://hallvards.blogspot.com/2004/06/hack-6checking-for-valid-object.html)

).

Вот еще один:

function ValidateObj(Obj: TObject): Pointer;
// see { Virtual method table entries } in System.pas
begin
  Result := Obj;
  if Assigned(Result) then
    try
      if Pointer(PPointer(Obj)^) <> Pointer(Pointer(Cardinal(PPointer(Obj)^) + Cardinal(vmtSelfPtr))^) then
        // object not valid anymore
        Result := nil;
    except
      Result := nil;
    end;
end;

Обновление: немного осторожности ... Приведенная выше функция гарантирует, что результат будет либо нулевым, либо действительным ненулевым объектом. Это не гарантирует, что Obj по-прежнему остается тем, чем вы думаете, в случае, когда диспетчер памяти уже перераспределил ранее освобожденную память.

3 голосов
/ 22 сентября 2008

Нет. Если вы не используете что-то вроде подсчета ссылок или сборщика мусора, чтобы убедиться, что ни один объект не будет освобожден до того, как у него будет нулевое число ссылок.

Delphi может сделать подсчет ссылок для вас, если вы используете интерфейсы. Конечно, в Delphi для .Net есть сборщик мусора.

Как уже упоминалось, вы можете использовать знания Delphi или внутреннюю часть диспетчера памяти для проверки на наличие действительных указателей или объектов, но они не единственные, которые могут дать вам указатели. Таким образом, вы не можете охватить все указатели даже с этими методами. И есть также шанс, что ваш указатель снова окажется действительным, но передан кому-то еще. Так что это не указатель, который вы ищете. Ваш дизайн не должен полагаться на них. Используйте инструмент для обнаружения любых ссылочных ошибок, которые вы делаете.

1 голос
/ 22 сентября 2008

Обычно в любом случае не рекомендуется проверять действительность ссылки. Если ссылка недействительна, ваша программа потерпит крах в том месте, где она использует недопустимую ссылку. В противном случае недействительная ссылка может сохраниться дольше, а отладка станет труднее.

Вот несколько ссылок на причины сбоя при неправильной ссылке. (Они говорят об указателях в Win32, но идеи все еще актуальны):

1 голос
/ 22 сентября 2008

Как уже говорили другие, нет определенного способа, но если вы хорошо управляете владением, тогда подпрограмма FreeAndNil будет гарантировать, что ваша переменная равна нулю, если она ни на что не указывает.

1 голос
/ 22 сентября 2008

Стандарт, нет ...

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

Так что, если вы хотите убедиться, что у вас нет недействительных ссылок, есть два варианта:

  • Реализация обработчика уведомлений об уничтожении, на который может подписаться каждый класс.
  • Исправьте ваш код таким образом, чтобы ссылки не распространялись через разные объекты. Например, вы можете предоставить доступ к ссылке только через свойство другого объекта. И вместо копирования ссылки на приватное поле вы получаете доступ к свойству другого объекта.
0 голосов
/ 10 ноября 2010

С использованием ссылок на интерфейсы (вместо ссылок на объекты) можно избежать этих проблем с недействительными указателями, поскольку в вашем коде больше нет явного вызова Free.

0 голосов
/ 22 сентября 2008

К сожалению, нет никакой возможности на 100% гарантировать, что указатель на что-либо еще действителен, кроме как путем тщательного написания правильного кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...