Почему при освобождении неверного указателя на объект выбрасывается EPrivilege вместо EAccessViolation? - PullRequest
2 голосов
/ 22 января 2012

Почему я получаю «EPrivilege - Privileged instruction» при выполнении этой процедуры вместо Access Violation?

{$Warnings OFF}
procedure TFrmMyTest.mnuCrashMeClick(Sender: TObject);
var t: TStringList;
begin
 FreeAndNil(t);
end;
{$Warnings ON}

Я знаю, что я пытаюсь освободить объект, который случайно указывает в памяти. Но я ожидаю получить нарушение доступа, а не «Привилегированную инструкцию».

(Не волнуйтесь, я не собираюсь использовать приведенный выше код в реальной программе.)

Ответы [ 2 ]

9 голосов
/ 22 января 2012

FreeAndNil вызывает не виртуальный метод Free. Который сначала проверяет nil (переменная скорее всего не nil), а затем вызывает виртуальный деструктор Destroy.

Вызов виртуального метода означает просмотр начала объекта для получения таблицы виртуальных методов (VMT). Это может привести к нарушению прав доступа. Но если объект находится в выделенной памяти, он вместо этого возвратит неопределенный указатель как VMT.

Затем значение размера указателя считывается с определенным смещением от VMT. Это еще раз может вызвать нарушение прав доступа или вернуть неопределенный указатель.

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

3 голосов
/ 22 января 2012

Иногда вы получаете нарушение прав доступа, а иногда - EPrivilege, и, без сомнения, существуют другие способы отказа.И даже иногда код будет работать, и сбой произойдет позже.Все зависит от того, какое значение будет в t, когда вы вызываете Free.

...