Нарушение доступа Delphi Чтение объекта из TStringsList - PullRequest
1 голос
/ 18 ноября 2010

Я получаю следующее

Access violation at address 00404340 in module 'test.exe'. Read of address FFFFFFD5

со следующим кодом

var
 List: TStrings;

В разделе создания:
List:= TStringList.Create;

Добавление в список:
Result := List.AddObject('hi', aCreatedObject); MessageDlg(FunctionHookList.Objects[Result].ClassName, mtInformation, [mbOK], 0);

В диалоге сообщений отображается правильное имя класса

Но позже, когда я это сделаю,

i := list.IndexOf('hi');
   if i >= 0 then
      if list.Objects[i] <> nil then
        if assigned(list.Objects[i]) then
          begin
           tmp := list.Objects[i];
           if tmp <> nil then
                MessageDlg(tmp.ClassName, mtInformation, [mbOK], 0); //*******
          end;  

Я получил сообщение о нарушении прав доступа выше по //******* строке

Я знаю, что там есть немного дублированного кода, но я пытался проверить 'все'

Ответы [ 2 ]

2 голосов
/ 18 ноября 2010

Похоже, ваша программа читает с отрицательного смещения нулевого указателя.Смещение отключено на единицу от смещения, в котором имя класса хранится в VMT, предполагая, что поле, в котором объект хранит указатель VMT , содержит адрес 1 вместо фактического адреса VMT своего класса.

Это ставит под вопрос, действительно ли вы сохранили действительную ссылку на объект в этом списке.Вы добавляете что-то к List, но затем, чтобы проверить, что это работает, вы печатаете значение ClassName какого-то объекта в FunctionHookList.Какая причина верить, что это один и тот же объект?Проверьте, как вы сконструировали объект, а затем проверьте оператор присваивания, который присваивает значение переменной aCreatedObject.Ищите сомнительные операции с памятью, например, вызывая Move или TStream.Read, где вы указали неправильный указатель назначения или неправильный счетчик байтов, перезаписывая, таким образом, часть объекта.

Чтобы выяснить, что происходитвызовите функцию ClassType для объекта в списке.(Это обычно безопасно вызывать, потому что пока указатель хранится в ссылочных точках объекта где-то , вы получите значение. Может быть, не допустимое значение, но по крайней мере ононе вылетит.) Сравните результат с классом, который вы ожидаете в списке.Например, если вы сохранили TFont в списке, проверьте это:

tmp := list.Objects[i];
if tmp.ClassType <> TFont then
  ShowMessage(Format('Expected %p but got %p instead',
    [Pointer(TFont), Pointer(tmp.ClassType)]));
1 голос
/ 18 ноября 2010

Обратите внимание, что Assigned не проверяет ничего, кроме nil . Если вы поместите объект в список строк, освободите его, а затем проверите список строк, он скажет вам, что объект все еще существует. Проверьте этот пример:

var
  o: TObject;
begin
  o := TObject(42 {just a random number});
  if Assigned(o) then
    ShowMessage(o.ClassName);
end;

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

...