2010-11-18 53 views
1

即时得到以下德尔福访问冲突读取对象从TStringsList

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; 

我得到的访问冲突高于上//*******线

我知道有有一些重复代码,但我试图检查'所有'

+1

当你说“以后”时,你是什么意思?也许aCreatedObject在那个时候已经被销毁,并且list.Objects [i]返回一个无效的对象。请在变量声明的一个完整函数中发布示例。 – Ozan 2010-11-18 05:39:01

+0

如果索引i处的对象为零,则您的代码会检查两次,如果指定了对象,则检查两次。您可以将Objects [i]分配给tmp一次,然后检查tmp:'if i> = 0,然后开始tmp:= Objects [i];如果分配了(tmp),那么...' – mjn 2010-11-18 08:10:35

+0

@Ozan,可能是aCreatedObject可能已经被销毁,我认为如果是的话,我过度使用'<> nil'和'assigned'就会捕获它。 – 2010-11-18 23:26:46

回答

1

请注意,分配不检查任何东西,除了。如果你将一个对象放在字符串列表中,将其释放,然后检查字符串列表,它会告诉你还有一个对象。检查这个例子:

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

因此,几乎所有的检查都是有效的,除了分配。它只检查对象是否包含除nil以外的任何其他值,这与您在上面的行上执行的检查基本相同。

2

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

这会引发您是否确实在该列表中存储了有效的对象引用的问题。您正在向List添加某些内容,但为了测试它的工作情况,您正在输出FunctionHookList中某个对象的ClassName值。有什么理由相信这些是同一个对象?检查构建对象的方式,然后检查赋予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)]));