I always get an access violation when I try to use the DocumentElement
of the XMLDocument
. I create XMLDocument
based on the existence of some file.
Error message
Project project1.exe raised exception class EAccessViolation with message 'Access violation at address 0047B152 in module 'project1.exe'.Read of Address B1D59357'
My code
unit XMLBase;
interface
uses
SysUtils, xmldom, XMLIntf, XMLDoc, Forms;
type
TXMLbase = class
private
{ Private declarations }
public
XMLDocument1: TXMLDocument;
root: IXMLNode;
constructor Create;
end;
var
fn: string;
implementation
constructor TXMLbase.Create;
begin
fn := ChangeFileExt(Application.ExeName, '.xml');
XMLDocument1 := TXMLDocument.Create(nil);
XMLDocument1.Options := [doNodeAutoIndent];
XMLDocument1.Active := False;
//optional, is used to indent the Xml document
if FileExists(fn) then
begin
XMLDocument1.LoadFromFile(fn);
XMLDocument1.Active:= True;
root := XMLDocument1.DocumentElement; //<<--- Access Voilation
end
else
begin
XMLDocument1.Active := False;
XMLDocument1.XML.Text := '';
XMLDocument1.Active := True;
root := XMLDocument1.AddChild('Settings');
end;
XMLDocument1.SaveToFile(fn);
end;
end.
Access violations arise due to improper initialization of object or pointers, does that mean that the XMLDocument
is not being initialized?
You are passing
nil
toTXMLDocument.Create
. When you do this, the object behaves likeTInterfacedObject
. It's lifetime is managed by interface reference counting. But you are not holding a reference to an interface.The documentation covers this in some detail.
If you enable Debug DCUs and set a breakpoint in
TXMLDocument.Destroy
you can observe the object being destroyed just before your access violation.Solve the problem by either:
XMLDocument1
asIXMLDocument
.Do make sure you do one or other of these, but not both!
As indicated by David just changing your XMLDocument1 declaration from
XMLDocument1: TXMLDocument
toXMLDocument1: IXMLDocument
solves the problem. Your issue is related to Using TXmlDocument