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.
精彩评论