1
votes

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'

2
What do you mean when you say "later"? Maybe aCreatedObject has been destroyed at that time and list.Objects[i] returns an invalid object. Please post an example within one complete function with variable declarations. - Ozan
your code checks twice if the object at index i is nil, and one time if it is assigned. You can assign Objects[i] to tmp once and check on tmp: if i >= 0 then begin tmp := Objects[i]; if Assigned(tmp) then ... - mjn
@Ozan, it is possible that aCreatedObject might have been destroyed, i thought that my over use of <> nil and assigned would catch it if it was. - Christopher Chase
@mjustin my original code did look some what like that, but i keep adding checks in hope of finding some kinda answer. i was going to 're'simplify it after it got it working - Christopher Chase

2 Answers

2
votes

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

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.