Delphi访问冲突从TStringsList读取对象

时间:2010-11-18 05:16:11

标签: delphi delphi-7 access-violation

我得到以下

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 个答案:

答案 0 :(得分:2)

看起来你的程序正在读取空指针的负偏移量。偏移量与存储在VMT中的类名称的偏移量相差一,表明对象存储其VMT指针的字段保存地址1而不是其类的VMT的实际地址。

这使人怀疑是否确实在该列表中存储了有效的对象引用。您正在向List添加内容,但是,为了测试它是否有效,您将在ClassName中打印某个对象的FunctionHookList值。有什么理由相信那些是同一个对象?检查构造对象的方式,然后检查赋值aCreatedObject变量的赋值语句。查找可疑的内存操作,例如调用MoveTStream.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 :(得分:1)

请注意,Assigned不会检查任何内容,但 nil 除外。如果你把一个对象放在stringlist中,释放它,然后检查stringlist,它会告诉你还有一个对象。检查此示例:

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

所以几乎所有的支票都是有效的,除了指定的。它只检查对象是否包含除nil之外的任何其他值,它与上面的行执行的检查基本相同。