Где этот неверный указатель? - PullRequest
3 голосов
/ 16 августа 2011

У меня следующий код (я проверил, что objCur не равен Nil до освобождения):

try
  objCur.Free;
Except on E:Exception do
  begin
    OutputDebugString(PChar('Exception '+E.Message));
    Assert(False);
  end;
end;

Он сообщает об этом исключении:

Недопустимая операция с указателем. ObjCur имеет тип TXX_TEA.
objCur: TXX_TEA;

В TXX_TEA.Destroy у меня есть следующий код

destructor TXX_TEA.Destroy;
begin
  OutputDebugString(PChar('Inside Destroy'));
  ...
  inherited;
  OutputDebugString(PChar('End of Destroy'));
end;

В debugView я вижу следующие сообщения:

Inside Destroy
...
End of Destroy

Исключение: недопустимая операция с указателем

Я знаю, что objCur.Free вызывает TXX_TEA.Destroy, но выглядит как TXX_TEA.Destroy.выполняется без ошибок. Так, где я должен отследить эту недопустимую операцию указателя?

Ответы [ 3 ]

9 голосов
/ 16 августа 2011

Недопустимая операция указателя происходит, когда диспетчеру памяти предлагается освободить память, которая ему не принадлежит.

Память объекта освобождается непосредственно перед тем, как внешний деструктор возвращается к вызывающей стороне.Звонящий в этом случае - TObject.Free.Вызов inherited не приводит к освобождению памяти объекта, поскольку компилятор знает, что это не внешний вызов.

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

6 голосов
/ 16 августа 2011

Операция с неверным указателем, когда вы пытаетесь освободить что-то, почти всегда означает, что оно уже освобождено.Если вы хотите найти где, самый простой способ - это получить полную версию FastMM от SourceForge.Прочитайте документацию, и она покажет вам, как добавить ее в ваш проект и как включить FullDebugMode.При включенном FullDebugMode, когда вы пытаетесь освободить то, что уже было освобождено, оно прерывает программу диалоговым окном, которое дает вам, среди прочего, трассировку стека, когда объект был освобожден в первый раз.Это должно помочь вам отследить ошибку.

3 голосов
/ 16 августа 2011

Вполне вероятно, что у вас все еще есть ссылка на него, и что некоторый код использует эту ссылку для доступа к объекту после его освобождения. Это может быть ссылка на объект или ссылка на интерфейс (ссылки на интерфейсы, отличные от nil, будут вызывать _Release в конце области видимости).

Нам нужно увидеть больше кода, чтобы действительно выяснить, что его вызывает.

...