Delphi 访问冲突从 TStringsList 读取对象

发布于 2024-10-03 14:37:48 字数 825 浏览 0 评论 0原文

收到以下

我在模块“test.exe”中的地址 00404340 处 读取地址 FFFFFFD5

使用以下代码

var
 List: TStrings;

访问冲突。在创建部分中 :
List:= TStringList.Create;

添加到列表:
结果 := 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;  

我在 < code>//******** 行

我知道那里有一些重复的代码,但我试图检查'所有内容'

Im getting the following

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

with the following code

var
 List: TStrings;

In the Create Section:
List:= TStringList.Create;

Adding to the list:
Result := List.AddObject('hi', aCreatedObject);
MessageDlg(FunctionHookList.Objects[Result].ClassName, mtInformation, [mbOK], 0);

The Message dialog shows the correct classname

But later when i do,

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;  

i get the Access violation above at on the //******* line

I know there is a bit of duplicated code there, but i was trying to check 'everything'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

來不及說愛妳 2024-10-10 14:37:48

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

这就让人怀疑您是否真的在该列表中存储了有效的对象引用。您正在向 List 添加一些内容,但是为了测试它是否有效,您正在打印 FunctionHookList 中某个对象的 ClassName 值。有什么理由相信它们是同一个物体?检查如何构造该对象,然后检查为 aCreatedObject 变量赋值的赋值语句。查找有问题的内存操作,例如在调用 MoveTStream.Read 时指定了错误的目标指针或错误的字节计数,从而覆盖了对象的一部分。

为了帮助了解发生了什么,请调用 ClassType< /a> 作用于列表中的对象。 (这通常是安全的调用,因为只要存储在对象引用中的指针指向某个地方,您就会得到一个值。也许不是有效值,但在至少它不会崩溃。)将结果与您期望在列表中的类进行比较。例如,如果您在列表中存储了 TFont,则测试以下内容:

tmp := list.Objects[i];
if tmp.ClassType <> TFont then
  ShowMessage(Format('Expected %p but got %p instead',
    [Pointer(TFont), Pointer(tmp.ClassType)]));

It looks like your program is reading from a negative offset of a null pointer. The offset is off by one from the offset where the class name stored in the VMT, suggesting that the field where the object stores its VMT pointer holds the address 1 instead of the actual address of its class's VMT.

That calls into question whether you really stored a valid object reference in that list. You're adding something to List, but then, to test that it worked, you're printing the ClassName value of some object in FunctionHookList. What reason is there to believe those are the same object? Check how you constructed the object, and then check the assignment statement that gives a value to the aCreatedObject variable. Look for questionable memory operations, like calling Move or TStream.Read where you specified the wrong destination pointer or a wrong byte count, thus overwriting a portion of the object.

To help find out what's going on, call the ClassType function on the object in the list. (That's generally safe to call, because as long as the pointer stored in the object reference points somewhere, you'll get a value. Maybe not a valid value, but at least it won't crash.) Compare the result to the class you expect to be in the list. For example, if you stored a TFont in the list, then test this:

tmp := list.Objects[i];
if tmp.ClassType <> TFont then
  ShowMessage(Format('Expected %p but got %p instead',
    [Pointer(TFont), Pointer(tmp.ClassType)]));
埋情葬爱 2024-10-10 14:37:48

请注意,Assigned 不会检查除 nil 之外的任何内容。如果您将一个对象放入字符串列表中,释放它,然后检查字符串列表,它会告诉您仍然有一个对象。检查这个例子:

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

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

Please note that Assigned doesn't check anything, except for nil. If you put an object in the stringlist, free it, and then check the stringlist, it will tell you that there's still an object. Check this example:

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

So almost all your checks are valid, except the assigned. It only checks if the object contains any other value than nil, which it basically the same check you perform on the line above.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文