7

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?

Triber
  • 1,525
  • 2
  • 21
  • 38
Jatin Gera
  • 814
  • 1
  • 11
  • 25
  • the code breaks at line 32 and root is declared in public section – Jatin Gera Dec 25 '12 at 15:18
  • Well when I'm testing on an actual XML document, I'm getting `Invalid pointer operation` at no particular breakpoint, after the constructor completes. – Jerry Dodge Dec 25 '12 at 15:24
  • the Code runs fine when there is no XML Document and it produces single node '', however when run again it breaks any read attempt is made to document element. – Jatin Gera Dec 25 '12 at 15:26
  • If all you're doing is some application settings, then can an `INI File` work for what you need? XML is a bit much if you just need to store a few strings, but is great when you have an intricate group of settings. – Jerry Dodge Dec 25 '12 at 15:27
  • Can you validate your XML document against its XML schema (xsd)? – Jack G. Dec 25 '12 at 15:29
  • @J.Gonzalez It doesn't look like he's using a schema. – Jerry Dodge Dec 25 '12 at 15:32
  • Well if the problem was in the XML code its self, the error message would be more XML specific, rather than an A/V. Is this all your complete code? Or is there some stuff you removed so you could post it here? – Jerry Dodge Dec 25 '12 at 15:33
  • @ Jerry Dodge I was using Ini file previously,but there are lot of things i want to store that ini file does not support such as large amount of text. – Jatin Gera Dec 25 '12 at 15:37
  • Any chance you could create a XML schema then use the XML Wizard to access it, which would be easier than looping through the XML nodes and guarantee the Delphi/XML mapping. – Jack G. Dec 25 '12 at 15:42
  • you can get it from [link]http://rapidshare.com/files/1056241858/Project.7z[link] – Jatin Gera Dec 25 '12 at 15:44
  • @XPecto "Download not available: File ID Invalid" – Jerry Dodge Dec 26 '12 at 05:44
  • Google Drive [link]https://docs.google.com/open?id=0Bw9D_3GJ-a48WnFTaGRjd1lSY2c[link] Rapidshare Link:[link]https://rapidshare.com/files/1056241858/Project.7z[link] – Jatin Gera Dec 26 '12 at 14:51

2 Answers2

10

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!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • You see, I would have never discovered this. Thank God for people who know more about the internal workings. – Jerry Dodge Dec 25 '12 at 15:52
  • i have changed the default constructor to `constructor Create(Owner:TObject);` and passed from the form as `x:= TXMLbase.Create(Self);` but i am having the same problem. can you please show some example thankyou. – Jatin Gera Dec 25 '12 at 15:55
  • So somehow that explains at least a little bit why I get an `Invalid pointer operation` and you get an `Access violation` – Jerry Dodge Dec 25 '12 at 15:58
  • 2
    That's not enough! You have to pass the Owner on to the `TXMLDocument` constructor! Like this: `XMLDocument1 := TXMLDocument.Create(Owener)`. – David Heffernan Dec 25 '12 at 16:17
  • So, I looked a bit deeper. I'm 100% sure that my answer explains your problem. – David Heffernan Dec 25 '12 at 16:28
3

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

Community
  • 1
  • 1
Jack G.
  • 3,681
  • 4
  • 20
  • 24
  • 3
    Doesn't this just repeat one of the options that I gave, and omit the detail? – David Heffernan Dec 26 '12 at 13:47
  • @David The initial post did not provide a direct solution to the problem (just changing XMLDocument1: IXMLDocument). The 3rd edit does. Apologies for posting between the first and 3rd edit. How does one undo this stuff? – Jack G. Dec 26 '12 at 17:59
  • The original post included both possible solutions. – David Heffernan Dec 26 '12 at 18:10
  • I guess XPecto needed it spelling out with code. And I probably neglected that in favour of a wordy exposition. So, probably on me. :-) – David Heffernan Dec 26 '12 at 18:22