![]() |
Delphi-Version: 2009
TXmlDocument.Create(nil)
Moin allerseits,
in einer Mainform-Unit verwende ich folgende Methode zum Öffnen einer XML-Datei problemlos:
Delphi-Quellcode:
Nun möchte ich aber das XML-Handling in eine Klasse auslagern und kann dort natürlich nicht self als Eigentümer bei Erzeugen der TXmlDocument-Instanz angeben, sondern muß mich mit nil begnügen:
procedure TFormMain.XMLfile_Open(const Datei: String);
Var XmlDok : TXmlDocument; Root : IXmlNode; Txt : String; begin XmlDok := TXmlDocument.Create(self); Try XmlDok.LoadFromFile(Datei); Root := XmlDok.DocumentElement; If Root.HasChildNodes Then Begin Txt := Root.ChildNodes['rootfiles'].ChildNodes['rootfile'].AttributeNodes['full-path'].Text; Memo1.Lines.Append(Txt); End; Finally XmlDok.Free; End; end;
Delphi-Quellcode:
Das führt jedoch zu einem Laufzeitfehler:
XmlDok := TXmlDocument.Create(nil);
Im Projekt XMLTEST.exe ist eine Exception der Klasse EInvalidPointer mit der Meldung 'Ungültige Zeigeroperation' aufgetreten. Was muß ich also tun, um TXmlDocument in einer eigenständigen Klasse zu verwenden, in der ich beim Erzeugen keinen Owner zuweisen kann? Eine mögliche Lösung wäre natürlich, die Klasse mit Owner zu erzeugen und diesen dann der TXmlDocument-Instanz als solchen zuzuweisen. Das funktioniert zwar, scheint mir aber intuitiv irgendwie nicht ganz das Richtige zu sein ... |
AW: TXmlDocument.Create(nil)
Erstell dir eine Dummy-TComponent-Instanz die du dem constructor übergibst. So funktionierts nicht.
|
AW: TXmlDocument.Create(nil)
Das Problem liegt in der gemischten Verwendung von Interfaces und der Klassen-Instanz.
Lösung:
Delphi-Quellcode:
, dann klappt es auch ohne Owner
XmlDok:IXmlDocument;
|
AW: TXmlDocument.Create(nil)
Zitat:
Zitat:
Delphi-Quellcode:
wird ja bereits beim Versuch, auf das Root-Element zuzugreifen, ausgelöst. Und
XmlDok := TXmlDocument.Create(nil);
Delphi-Quellcode:
ist doch eine Eigenschaft von
TXmlDocument.DocumentElement
Delphi-Quellcode:
, oder etwa nicht?
TXmlDocument
Zitat:
Delphi-Quellcode:
Der Versuch, ein XML-Dokument zu laden, löst jedoch eine Zugriffsverletzung aus:
procedure TFormMain.XMLfile_Open(const Datei: String);
Var XmlDok : IXmlDocument; Root : IXmlNode; Txt : String; begin Try XmlDok.LoadFromFile(Datei); // erzeugt Zugriffsverletzung Root := XmlDok.DocumentElement; If Root.HasChildNodes Then Begin Txt := Root.ChildNodes['rootfiles'].ChildNodes['rootfile'].AttributeNodes['full-path'].Text; Memo1.Lines.Append(Txt); End; Finally XmlDok := nil; End; end; Im Projekt XMLTEST.exe ist eine Exception der Klasse EAccessViolation mit der Meldung 'Zugriffsverletzung bei Adresse 0047C70D in Modul 'XMLTEST.exe'. Lesen von Adresse 00000000' aufgetreten. |
AW: TXmlDocument.Create(nil)
Du sollst auch nur das machen, was ich dir gesagt habe.
Ändere nur deinen Original-Code wie folgt ab:
Delphi-Quellcode:
var
XmlDok: {TXmlDocument} IXmlDocument; begin // keine Änderung am Original-Code! XmlDok := TXmlDocument.Create( nil ); ... // ok, try finally und das Free kann ersatzlos gestrichen werden end; |
AW: TXmlDocument.Create(nil)
Okay, das funktioniert tatsächlich :thumb:
Aber ich versteh's nicht: Ich deklariere eine Variable vom Typ IXmlDocument und erzeuge damit eine Instanz der Klasse TXmlDocument? Was passiert da? Als laienhafte Antwort fällt mir da nur sowas wie "... da muß wohl irgendwie das Interface mit eingebunden werden ..." ein ... Dann schreibst du noch: " try finally und das Free kann ersatzlos gestrichen werden". Ich habe aber irgendwo in der Online-Hilfe gelesen, wenn man TXmlDocument ohne Owner (nil) erzeugt, muß man diese Instanz am Ende wieder auf nil setzen. Mit Owner würde das der Owner übernehmen. Doch offenbar entstehen auch so keine Speicherlecks. |
AW: TXmlDocument.Create(nil)
Du erzeugst hier eine reference-counted Interface-Instanz.
Sobald der Referenz-Zähler einmal erhöht wurde und wieder auf 0 geht, wird die Instanz verworfen. Gibst du jetzt den Owner mit an, so wird der Referenz-Zähler auf 1 gesetzt und die Instanz verschwindet mit dem Owner. Hier kannst du gefahrlos mit der normalen Klassen-Referenz arbeiten. Ohne Owner bleibt der Zähler erst mal auf 0, aber jeder Zugriff auf eine Node, ... arbeitet auch intern mit der Interface-Referenz des Dokuments ... und wenn diese Referenz losgelassen wird ... geht der Referenz-Zähler auf 0 und ... genau räumt dir die Xml-Instanz aus dem Speicher. Abhilfe schafft also selber den Referenz-Zähler zu erhöhen (ich nehme
Delphi-Quellcode:
), somit ist der Zähler immer mindestens 1, bis ich die Referenz auf
IXmlDocument
Delphi-Quellcode:
setze, oder die Methode verlassen wird und die lokale Variable aus dem Scope geht (dann wird die auch auf
nil
Delphi-Quellcode:
gesetzt).
nil
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:56 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz