我得到以下
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;
我在//*******
行
我知道那里有一些重复的代码,但我试图检查'所有'
答案 0 :(得分:2)
看起来你的程序正在读取空指针的负偏移量。偏移量与存储在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 :(得分: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之外的任何其他值,它与上面的行执行的检查基本相同。