AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TXmlDocument.Create(nil)

Ein Thema von Perlsau · begonnen am 2. Aug 2015 · letzter Beitrag vom 2. Aug 2015
Antwort Antwort
Perlsau
(Gast)

n/a Beiträge
 
#1

TXmlDocument.Create(nil)

  Alt 2. Aug 2015, 11:00
Delphi-Version: 2009
Moin allerseits,

in einer Mainform-Unit verwende ich folgende Methode zum Öffnen einer XML-Datei problemlos:
Delphi-Quellcode:
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;
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:
  XmlDok := TXmlDocument.Create(nil); Das führt jedoch zu einem Laufzeitfehler:

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 ...

Geändert von Perlsau ( 2. Aug 2015 um 11:23 Uhr) Grund: mögliche Lösung
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: TXmlDocument.Create(nil)

  Alt 2. Aug 2015, 12:48
Erstell dir eine Dummy-TComponent-Instanz die du dem constructor übergibst. So funktionierts nicht.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: TXmlDocument.Create(nil)

  Alt 2. Aug 2015, 13:05
Das Problem liegt in der gemischten Verwendung von Interfaces und der Klassen-Instanz.

Lösung: XmlDok:IXmlDocument; , dann klappt es auch ohne Owner
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#4

AW: TXmlDocument.Create(nil)

  Alt 2. Aug 2015, 15:08
Erstell dir eine Dummy-TComponent-Instanz die du dem constructor übergibst. So funktionierts nicht.
Doch, mit der letztgenannten Lösung funktioniert es tatsächlich: Ich weise dem Create der Klasseninstanz als Owner das aufrufende Formular zu und kann dann ohne Probleme diesen Owner auch der Instanz von TXmlDocument zuweisen.

Das Problem liegt in der gemischten Verwendung von Interfaces und der Klassen-Instanz.
Was meinst du damit genau? Wo verwende ich diese beiden gemischt? Der Fehler in der ersten Variante XmlDok := TXmlDocument.Create(nil); wird ja bereits beim Versuch, auf das Root-Element zuzugreifen, ausgelöst. Und TXmlDocument.DocumentElement ist doch eine Eigenschaft von TXmlDocument , oder etwa nicht?

Lösung: XmlDok:IXmlDocument; , dann klappt es auch ohne Owner
Okay, das habe ich versucht. IXmlDocument kann nicht erzeugt werden, denn es verfügt nicht über eine Create-Methode.
Delphi-Quellcode:
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;
Der Versuch, ein XML-Dokument zu laden, löst jedoch eine Zugriffsverletzung aus:

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.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: TXmlDocument.Create(nil)

  Alt 2. Aug 2015, 15:13
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;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 2. Aug 2015 um 15:15 Uhr)
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#6

AW: TXmlDocument.Create(nil)

  Alt 2. Aug 2015, 15:29
Okay, das funktioniert tatsächlich

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.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: TXmlDocument.Create(nil)

  Alt 2. Aug 2015, 15:46
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 IXmlDocument ), somit ist der Zähler immer mindestens 1, bis ich die Referenz auf nil setze, oder die Methode verlassen wird und die lokale Variable aus dem Scope geht (dann wird die auch auf nil gesetzt).
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:58 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz