开发者

Delphi Access violation Reading Object From TStringsList

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;

Ad开发者_StackOverflowding 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'


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)]));


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜