Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2008-10

XML and memory loss

7 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bart

Hi all,

I am totaly nes to this (XML), so I suppose i do something wrong.

I took the example from the Wiki XML Tutorial, and the simplified it. (I use Lazarus svn revision 16824, with fpc 2.2.0 on Window ME)

Here's my code to write an XML file:

procedure TForm1.Button1Click(Sender: TObject);
var
  xdoc: TXMLDocument;                                  // variable to
document
  RootNode, parentNode, nofilho: TDOMNode;                    // variable to
nodes
  Fn: String;
begin
  Fn := 'F:\LazarusProjecten\XMLTest\test1.xml';
  //create a document
  xdoc := TXMLDocument.create;
  xdoc.Encoding := 'utf-8';
  //create a root node
  RootNode := xdoc.CreateElement('root');
  Xdoc.Appendchild(RootNode);                           // save root node
  //create a parent node
  RootNode:= xdoc.DocumentElement;
  parentNode := xdoc.CreateElement('child');
  RootNode.Appendchild(parentNode);                          // save parent
node
  //create a child node
  parentNode := xdoc.CreateElement('foo');                // create a child
node
  //nofilho := xdoc.CreateTextNode('Bart');         // insert a value to
node
  //parentNode.Appendchild(nofilho);                         // save node
  RootNode.ChildNodes.Item[0].AppendChild(parentNode);       // insert child
node in respective parent node
  //create a second child node
  parentNode := xdoc.CreateElement('bar');               // create a child
node
  //nofilho := xdoc.CreateTextNode('me, myself and I');               //
insert a value to node
  //parentNode.Appendchild(nofilho);                         // save node
  RootNode.ChildNodes.Item[0].AppendChild(parentNode);       // insert a
childnode in respective parent node
  writeXMLFile(xDoc,Fn);                     // write to XML
  Xdoc.free;                                          // free memory
  Memo1.Lines.LoadFromFile(Fn);
end;

This creates the following XML file:
<?xml version="1.0"?>
<root>
<child>
<foo/>
<bar/>
</child>
</root>

This file is more or less as I excpected it to be (i would think it would include the encoding="utf-8").

The problem is, that for every child I create and append, I loose 4 blocks of memory (60 bytes for these 4 blocks) (I used the heaptrace option with compilation).
I commented out the CreateTetNode to try and see if it made any difference in the (amount of) memory loss, but it seems to have no effect at all.

(I cannot include the total heaptrace report, since on win9x it's output cannot be redirected, and the win9x console cannot be scrolled...)

What am I doing wrong here?

Bart
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20081008/7f2c6783/attachment.html

Reply by email

Sergei Gorelkin
to Bart

Bart wrote:

...

This file is more or less as I excpected it to be (i would think it would include the encoding="utf-8").

Currently changing the encoding is not supported, and files are always written in utf-8 encoding. According to the XML specs, files without encoding label are read as utf-8, so this is by design.

The problem is, that for every child I create and append, I loose 4 blocks of memory (60 bytes for these 4 blocks) (I used the heaptrace option with compilation).

The memory leak is caused by using the ChildNodes property. Each time you use it, a new TDOMNodeList object is created, which must be eventually destroyed by calling Free. The FCL DOM implementation does not offer automatic memory management here, unlike other implementations.

Some time ago I updated the English page of Wiki tutorial to reflect this fact.

In your case, ChildNodes.Item[0] can be replaced by FirstChild, which will return exactly the same node.

Regards,
Sergei

Reply by email

Jesus Reyes
to Sergei Gorelkin

--- El mi? 8-oct-08, Sergei Gorelkin escribi?:

Show quoted text 44 lines
De:: Sergei Gorelkin Asunto: Re: [Lazarus] XML and memory loss A: "General mailing list" Fecha: mi?rcoles, 8 octubre, 2008, 10:49 am Bart wrote: ... > > This file is more or less as I excpected it to be (i would think it > would include the encoding="utf-8"). Currently changing the encoding is not supported, and files are always written in utf-8 encoding. According to the XML specs, files without encoding label are read as utf-8, so this is by design. > > The problem is, that for every child I create and append, I loose 4 > blocks of memory (60 bytes for these 4 blocks) (I used the heaptrace > option with compilation). The memory leak is caused by using the ChildNodes property. Each time you use it, a new TDOMNodeList object is created, which must be eventually destroyed by calling Free. The FCL DOM implementation does not offer automatic memory management here, unlike other implementations. Some time ago I updated the English page of Wiki tutorial to reflect this fact. In your case, ChildNodes.Item[0] can be replaced by FirstChild, which will return exactly the same node. Regards, Sergei

By the way, and taking the fact that xml files are stored always in utf-8 encoding it's surprising that for example XMLConfig doesn't have a way to set a value which is already utf-8 encoded. so, any change to add a methods that take utf-8 encoded strings as arguments?, this way it could ve avoided unnecesary conversions.

Jesus Reyes A.

?Todo sobre Amor y Sexo!
La gu?a completa para tu vida en Mujer de Hoy.
http://mx.mujer.yahoo.com/

Reply by email

Sergei Gorelkin
to Jesus Reyes
Jesus Reyes wrote
By the way, and taking the fact that xml files are stored always in utf-8 encoding it's surprising that for example XMLConfig doesn't have a way to set a value which is already utf-8 encoded. so, any change to add a methods that take utf-8 encoded strings as arguments?, this way it could ve avoided unnecesary conversions.

The writer wasn't utf-8 capable at the time of writing TXMLConfig. Even if you add utf-8 methods to TXMLConfig, certain conversions will stay because underlying DOM is WideString-based.
After adding utf-8 to the writer, I've chosen to write a new unicode-enabled config class instead of modifying the old one and risk breaking the existing code. The new component is in the xmlconf unit, and it takes WideString arguments.

Regards,
Sergei

Reply by email

Bart
to Sergei Gorelkin: ... Currently changing the encoding is not supported, and files are always written in…
Show quoted text 5 lines
The memory leak is caused by using the ChildNodes property. Each time you use it, a new TDOMNodeList object is created, which must be eventually destroyed by calling Free. The FCL DOM implementation does not offer automatic memory management here, unlike other implementations.

Then how can I free those TDOMNodeList objects? I.o.w. how can I get access to them?

Some time ago I updated the English page of Wiki tutorial to reflect

this fact.

Yep, just re-read the article and saw the note...

In your case, ChildNodes.Item[0] can be replaced by FirstChild, which

will return exactly the same node.

I tried that, and it wordk like a charm.
However can I use that approach if I want to create more complex XML files?

Eventually I want someting like this:
<?xml version="1.0"?>
<root>
<version>foo bar version 0.0.1</version>
<children>
<child id="0001">
<foo>Bart</foo>
<bar>me, myself and I</bar>
</child>
<child id="0002">
<foo>Bob</foo>
<bar>blah</bar>
</child>
<children/>
</root>

Bart
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20081009/22ffed29/attachment.html

Reply by email

Sergei Gorelkin
to Bart
Bart wrote
Then how can I free those TDOMNodeList objects? I.o.w. how can I get access to them?

You just put them into a variable and later call Free:

var
   Nodes: TDOMNodeList;
...
Nodes := MyNode.ChildNodes;
writeln(Nodes[0].NodeName);
...
Nodes.Free
Show quoted text 19 lines
I tried that, and it wordk like a charm. However can I use that approach if I want to create more complex XML files? Eventually I want someting like this: <?xml version="1.0"?> <root> <version>foo bar version 0.0.1</version> <children> <child id="0001"> <foo>Bart</foo> <bar>me, myself and I</bar> </child> <child id="0002"> <foo>Bob</foo> <bar>blah</bar> </child> <children/> </root>

In general, any tree can be built using only the AppendChild method. Just put necessary nodes in variables. Here is your example:

var
   doc: TXMLDocument;
   root, tmp, children, foo, bar: TDOMNode;
begin
   doc := TXMLDocument.Create;
   root := doc.CreateElement('root');
   doc.AppendChild(root);
   tmp := doc.CreateElement('version');
   tmp.AppendChild(doc.CreateTextNode('foo bar version 0.0.1'));
   root.AppendChild(tmp);
   children := doc.CreateElement('children');
   root.AppendChild(children);
   // first child
   tmp := doc.CreateElement('child');
   tmp['id'] := '0001';
   foo := doc.CreateElement('foo');
   foo.AppendChild(doc.CreateTextNode('Bart'));
   tmp.AppendChild(foo);
   bar := doc.CreateElement('bar');
   bar.AppendChild(doc.CreateTextNode('me, myself and I'));
   tmp.AppendChild(bar);
   children.AppendChild(tmp);
   // second child
   tmp := doc.CreateElement('child');
   tmp['id'] := '0002';
   foo := doc.CreateElement('foo');
   foo.AppendChild(doc.CreateTextNode('Bob'));
   tmp.AppendChild(foo);
   bar := doc.CreateElement('bar');
   bar.AppendChild(doc.CreateTextNode('blah'));
   tmp.AppendChild(bar);
   children.AppendChild(tmp);
end;

Regards,
Sergei

Reply by email

Bart
to Sergei Gorelkin
Sergei Gorelkin wrote 16 lines
Bart wrote: > > Then how can I free those TDOMNodeList objects? I.o.w. how can I get > access to them? > You just put them into a variable and later call Free: var Nodes: TDOMNodeList; ... Nodes := MyNode.ChildNodes; writeln(Nodes[0].NodeName); ... Nodes.Free

How should I apply that to my code-example?

Show quoted text 5 lines
In general, any tree can be built using only the AppendChild method. Just put necessary nodes in variables. Here is your example: [snip]

I tried the examplecode, I had to replace

  tmp['id'] := '0001';

with

  TDOMElement(tmp).SetAttribute('id', '001');

(it would not compile otherwise: the error said something about tmp not having a default property)

This code creates the xml-file like I wanted it.
I'm going to study the code and try to understand it.

Thanks for the help!

Bart
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.lazarus.freepascal.org/pipermail/lazarus/attachments/20081009/8f182822/attachment.html

Reply by email