Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access violation when using DocumentElement In XMLDocument

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?

like image 671
Jatin Gera Avatar asked Dec 25 '12 15:12

Jatin Gera


2 Answers

You are passing nil to TXMLDocument.Create. When you do this, the object behaves like TInterfacedObject. 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.

When TXMLDocument is created without an Owner, it behaves like an interfaced object. That is, when all references to its interface are released, the TXMLDocument instance is automatically freed. When TXMLDocument is created with an Owner, however, it behaves like any other component, and is freed by its Owner.

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:

  1. Passing an owner when you create the document.
  2. Switch to using interfaces to refer to the object. That is declare XMLDocument1 as IXMLDocument.

Do make sure you do one or other of these, but not both!

like image 145
David Heffernan Avatar answered Oct 04 '22 03:10

David Heffernan


As indicated by David just changing your XMLDocument1 declaration from XMLDocument1: TXMLDocument to XMLDocument1: IXMLDocument solves the problem. Your issue is related to Using TXmlDocument

like image 32
Jack G. Avatar answered Oct 04 '22 05:10

Jack G.