Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   XML (https://www.delphipraxis.net/46-xml/)
-   -   Delphi Free von XML-Komponente führt zu EInvalidPointer exception (https://www.delphipraxis.net/179768-free-von-xml-komponente-fuehrt-zu-einvalidpointer-exception.html)

michele_tedesco 31. Mär 2014 10:45


Free von XML-Komponente führt zu EInvalidPointer exception
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo

Ich habe aus einem Form:
Delphi-Quellcode:
unit ViewXML;

interfaces
...

  TfrmXML = class(TForm)
...

var
  frmXML: TfrmXML;

implementation
....

procedure TfrmXML.Button2Click(Sender: TObject);
var
  XMLData: TXMLData;
begin
  if odXMLFile.Execute then
    frmXML.Caption := odXMLFile.FileName;
  try
    XMLData := TXMLData.Create;
    XMLData.XMLToTree(tvXML, odXMLFile.FileName);
  finally
    XMLData.Free;
  end;
end;
...
eine Komponente instantiiert und erhalte eine EInvalidPointer beim Free des Objekts.
Hier die Komponente:
Delphi-Quellcode:
unit ServiceXMLData;

interface
....

  TXMLData = class
  private
    FList: TList<string>;
    FDOC: IXMLDocument;
    FRootNode: IXMLNode;
    Procedure TreeToXML(const Tree: TTreeView);
    procedure IterateXMLNodes(xn: IXMLNode; ParentNode: TTreeNode; var Tree: TTreeView);
    procedure IterateTreeNodes(N: TTreeNode; var ParentXN: IXMLNode);
  public
    Constructor Create;
    Destructor Destroy; override;
    procedure Config;
    Procedure SaveToFile(const fn: String; const Tree: TTreeView);
    procedure XMLToTree(var Tree: TTreeView; const FileName: String);
  end;

implementation
uses
  System.Classes;

{ TXMLData }

procedure TXMLData.Config;
begin
//
end;

constructor TXMLData.Create;
begin
//
  FList := TList<string>.Create;
end;

destructor TXMLData.Destroy;
begin
  FList.Free;
  inherited;
end;


procedure TXMLData.IterateXMLNodes(xn: IXMLNode; ParentNode: TTreeNode; var Tree: TTreeView);
var
  i, j: Integer;
  ChildTreeNode, ChildAttributeTreeNode, ChildTextTreeNode: TTreeNode;
  XMLAttribute: TXMLAttribute;
begin
  For i := 0 to xn.ChildNodes.Count - 1 do
  begin
    if xn.ChildNodes[i].NodeType = TNodeType.ntElement then
    begin
      try
        { XML Node }
        ChildTreeNode := Tree.Items.AddChild(ParentNode, xn.ChildNodes[i].NodeName);
        { XML Node attributes }
        for j := 0 to xn.ChildNodes[i].AttributeNodes.Count -1 do
        begin
          { XML Node attribute key }
          ChildAttributeTreeNode := Tree.Items.AddChild(ChildTreeNode, xn.ChildNodes[i].AttributeNodes[j].NodeName);
          XMLAttribute := TXMLAttribute.create(CXMLAtribute);
          ChildAttributeTreeNode.Data := Pointer(XMLAttribute);
          { XML Node attribute value }
          ChildAttributeTreeNode := Tree.Items.AddChild(ChildAttributeTreeNode, xn.ChildNodes[i].AttributeNodes[j].NodeValue);
          XMLAttribute := TXMLAttribute.create(CXMLAtributeValue);
          ChildAttributeTreeNode.Data := Pointer(XMLAttribute);
        end;
      finally
        XMLAttribute.Free;
      end;
      { recursive call }
      IterateXMLNodes(xn.ChildNodes[i], ChildTreeNode, tree);
    end
    else if xn.ChildNodes[i].NodeType = TNodeType.ntText then
    begin
      try
        { XML Node value }
        ChildTextTreeNode := Tree.Items.AddChild(ParentNode, xn.ChildNodes[i].NodeValue);
        XMLAttribute := TXMLAttribute.create(CXMLText);
        ChildTextTreeNode.Data := Pointer(XMLAttribute);
      finally
        XMLAttribute.Free;
      end;
    end;
  end;
end;

procedure TXMLData.SaveToFile(const fn: String; const Tree: TTreeView);
begin
  FDOC := TXMLDocument.Create(nil);
  FDOC.Options := FDOC.Options + [doNodeAutoIndent];
  FDOC.Active := true;
  TreeToXML(tree);
  FDOC.SaveToFile(fn);
end;

procedure TXMLData.TreeToXML(const Tree: TTreeView);
var
  n: TTreeNode;
begin
  { Root node }
  FRootNode := FDOC.CreateElement('DSXMLExport', '');
  FDOC.DocumentElement := FRootNode;

  { iterate Tree }
  N := Tree.Items[0];
  while Assigned(N) do
  begin
    IterateTreeNodes(N, FRootNode);
    N := N.getNextSibling;
  end;
end;

procedure TXMLData.IterateTreeNodes(N: TTreeNode; var ParentXN: IXMLNode);
var
  CurrXMLNode: IXMLNode;
  Child: TTreeNode;
  s, t: string;
begin
  Child := N.getFirstChild;
  while Assigned(Child) do
  begin
    if Assigned(Child.Data) then
    begin
      { XML node value }
      s := Child.Text;
      try
        if TXMLAttribute(Child.Data).AttributeKey = CXMLText then
        begin
          ParentXN.Text := Child.Text
        end
        { XML node attribute }
        else if TXMLAttribute(Child.Data).AttributeKey = CXMLAtribute then
        begin
          ParentXN.Attributes[Child.Text] := Child.getFirstChild.Text;
        end;
      except
      on E : Exception do
        begin
          MessageDlg('Data of ' + s + ' could could not be read. Exception: '+ E.Message, mtInformation, [mbOK], 0);
        end;
      end;
    end
    else
    begin
      CurrXMLNode := ParentXN.AddChild(N.Text);
      //FDOC.SaveToXML(t);
      IterateTreeNodes(Child, CurrXMLNode);
    end;
    Child := Child.getNextSibling;
  end;
end;

procedure TXMLData.XMLToTree(var Tree: TTreeView; const FileName: String);
var
  Doc: IXMLDocument;
begin
  Doc := NewXMLDocument;
  Doc.LoadFromFile(FileName);
  Doc.Active;
  IterateXMLNodes(Doc.DocumentElement, nil, Tree);
end;

{ TXMLAttribute }

constructor TXMLAttribute.create(AttributeKey: string);
begin
  FAttributeKey := AttributeKey;
end;

function TXMLAttribute.GetAttributeKey: string;
begin
  result := FAttributeKey
end;

procedure TXMLAttribute.SetAttributeKey(s: string);
begin
  FAttributeKey := s;
end;

end.
UPDATE: Im Anhang die PAS-Datei für die XML Komponente

Union 31. Mär 2014 11:33

AW: Free von XML-Komponente führt zu EInvalidPointer exception
 
Das passiert womöglich nicht beim Free, sondern hier:
Delphi-Quellcode:
procedure TXMLData.XMLToTree(var Tree: TTreeView; const FileName: String);
var
  Doc: IXMLDocument;
begin
  Doc := NewXMLDocument;
  Doc.LoadFromFile(FileName);
  Doc.Active; // Diese Zeile macht nichts. Es muß heißen Doc.Active := True
  IterateXMLNodes(Doc.DocumentElement, nil, Tree);
end;

himitsu 31. Mär 2014 11:54

AW: Free von XML-Komponente führt zu EInvalidPointer exception
 
Da hier an vielen Stellen mit Interfaces gearbeitet wird, solltest du dringend auch die XML-Klasse nur via Interface verwenden!

michele_tedesco 31. Mär 2014 12:27

AW: Free von XML-Komponente führt zu EInvalidPointer exception
 
Zitat:

Zitat von Union (Beitrag 1254153)
Das passiert womöglich nicht beim Free, sondern hier:
Delphi-Quellcode:
procedure TXMLData.XMLToTree(var Tree: TTreeView; const FileName: String);
var
  Doc: IXMLDocument;
begin
  Doc := NewXMLDocument;
  Doc.LoadFromFile(FileName);
  Doc.Active; // Diese Zeile macht nichts. Es muß heißen Doc.Active := True
  IterateXMLNodes(Doc.DocumentElement, nil, Tree);
end;


Danke für dein Feedback :thumb: , aber das hat das Problem nicht gelöst :?

michele_tedesco 31. Mär 2014 12:28

AW: Free von XML-Komponente führt zu EInvalidPointer exception
 
Zitat:

Zitat von himitsu (Beitrag 1254158)
Da hier an vielen Stellen mit Interfaces gearbeitet wird, solltest du dringend auch die XML-Klasse nur via Interface verwenden!

Das ist mein nächster Schritt, jedoch will ich verstehen, wo der Fehler passiert, um diesen Fehler dann nicht mehr zu machen :wink:

baumina 31. Mär 2014 12:30

AW: Free von XML-Komponente führt zu EInvalidPointer exception
 
Wenn das Create schon gar nicht funktioniert, gibt's auch nichts das man freigeben könnte. Deswegen sollte das Create außerhalb vom try stehen.

Delphi-Quellcode:
 
XMLData := TXMLData.Create;
try
  XMLData.XMLToTree(tvXML, odXMLFile.FileName);
finally
  XMLData.Free;
end;

michele_tedesco 31. Mär 2014 12:51

AW: Free von XML-Komponente führt zu EInvalidPointer exception
 
gefunden :stupid:

Ich habe beim Zuweisen von .Data eines TreeItem "Pointer(XMLAttribute)" geschrieben, weil ich mit Interfaces am spielen war.
Hatte nicht fertig aufgeräumt.

Der korrekte Aufruf ist natürlich
Delphi-Quellcode:
TreeItem.Data := Object
, nicht
Delphi-Quellcode:
TreeItem.Data := Pointer(Object)

himitsu 31. Mär 2014 12:56

AW: Free von XML-Komponente führt zu EInvalidPointer exception
 
Zitat:

Zitat von datasportdev (Beitrag 1254164)
jedoch will ich verstehen, wo der Fehler passiert, um diesen Fehler dann nicht mehr zu machen :wink:

Wenn durch die Aufrufe der untergeordneten Interfaces die Referenzzählung in dem Interface-Objekt der XML-Klasse verändert werden, dann übernimmt die Referenzzählung die Kontrolle über das Objekt und ab dann darf Free nicht mehr aufgerufen werden.

Entweder die Freigabe eines Objektes geschieht manuell
oder die Freigabe geschieht ausschließlich über die automatische Referenzzählung. (also über Variablen des Interfacetyps, wobei es möglichst keine Objektreferenzen geben sollte)


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:38 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