Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   IXmlDocument wirft Exception (https://www.delphipraxis.net/206016-ixmldocument-wirft-exception.html)

Klaus01 10. Nov 2020 10:05

Delphi-Version: 10.3 Rio

IXmlDocument wirft Exception
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

mein Problem:
Diese Routine wirft beim Verlassen eine Exception:
Delphi-Quellcode:
procedure TCodeSystemReader.readFile(fileName: String);
var
  xmlDoc: IXmlDocument;
  xmlNode: IXmlNode;
  xmlNodeList: IXmlNodeList;
  i: Integer;
  csElement: TCodeSystemElement;
begin
  CoInitialize(nil);
  try
    xmlDoc := loadXmlDocument(fileName);
    xmlDoc.Active := true;
    xmlNodeList := xmlDoc.DocumentElement.ChildNodes;
    for i := 0 to xmlNodeList.Count -1 do
      begin
        xmlNode := xmlNodeList[i];
        if xmlNode.NodeName = 'cSystem' then
          begin
            csElement.codeValue := xmlNode.ChildNodes.findNode('code').Attributes['value'];
            csElement.displayValue := xmlNode.ChildNodes.FindNode('display').Attributes['value'];
            fCodeSystemList.Add(csElement);
          end;
      end;
  finally
    CoUnInitialize;
  end;
end;
Die Exception:
Code:
AccessViolation with message 'Zugriffsverletzung bei Adresse 00412C02 in Modul '....exe'. Lesen von Adresse 039D8C08'
Aufgerufen wird der Code in einem Unit-Test:
Delphi-Quellcode:
procedure TTestCodeSystemReader.readCodeSystemFile(const filename: String);
begin
  fCodeSystemReader := TCodeSystemReader.Create;
  try
    fCodeSystemReader.readFile(filename);
    assert.IsTrue(fCodeSystemReader.getCount > 0);
  finally
    fCodeSystemReader.Free;
  end;
end;
Der Stack: (siehe Anhang)
Wenn im debug mode "break" gedrückt wird, kommt das Programm hier zu stehen (system.pas)
Delphi-Quellcode:
function _IntfClear(var Dest: IInterface): Pointer;
{$IFDEF PUREPASCAL}
var
  P: Pointer;
begin
  Result := @Dest;
  if Dest <> nil then
  begin
    P := Pointer(Dest);
    Pointer(Dest) := nil;
    IInterface(P)._Release;
  end;
end;
{$ELSE !PUREPASCAL}
{$IFDEF CPUX86}
asm
        MOV    EDX,[EAX]
        TEST   EDX,EDX
        JE     @@1
        MOV    DWORD PTR [EAX],0
{$IFDEF ALIGN_STACK}
        SUB    ESP, 4
{$ENDIF ALIGN_STACK}
        PUSH   EAX
        PUSH   EDX
        MOV    EAX,[EDX] /// <---
        CALL   DWORD PTR [EAX] + VMTOFFSET IInterface._Release
        POP    EAX
{$IFDEF ALIGN_STACK}
        ADD    ESP, 4
{$ENDIF ALIGN_STACK}
Wenn jemand eine Idee hätte - wäre das prima.
Grüße
Klaus

EmWieMichael 10. Nov 2020 10:20

AW: TXmlDocument wirft Exception
 
Vielleicht hilft schon ein...
XMLDoc:=TXMLDocument.Create();

Klaus01 10. Nov 2020 10:37

AW: TXmlDocument wirft Exception
 
Danke - aber das hilft nicht weiter.
LoadXmlDocument gibt auch IXMLDocument zurück.
Das Lesen der Daten ist nicht das Problem - die Exception wird geworfen wenn die Routine verlassen wird.
Da werden dann auch die Interface (IXmlNode, IXmlNodeList und IXmlDocument) freigegeben weil der Scope verlassen wird.

EmWieMichael 10. Nov 2020 10:51

AW: TXmlDocument wirft Exception
 
Ach, sorry; ich hatte TXMDocument statt IXMLDocument gelesen...

Der schöne Günther 10. Nov 2020 11:16

AW: IXmlDocument wirft Exception
 
Ohne ein reproduzierbares Minimalbeispiel wird das schwierig. Was ist diese Liste? Was ist ein TCodeSystemElement? Das "IntfClear" spricht eigentlich dafür dass man hier durcheinander gekommen ist in Bezug auf Interface/TObject-Referenzierung. Er scheint also eine Interface-Variable freigeben zu wollen aber das dahinterliegende Objekt wurde bereits zerstört.

Auch: Mir ist das etwas gruselig in einer einzigen Methode CoInitialize / CoUnInitialize aufzurufen. Was ist wenn dein Destruktor oder sonstwas (unbewusst) noch etwas mit der MS-XML-Engine macht während du mit CoUnInitialize schon alles wieder abgebaut hast?

Klaus01 10. Nov 2020 11:25

AW: IXmlDocument wirft Exception
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1477020)
Auch: Mir ist das etwas gruselig in einer einzigen Methode CoInitialize / CoUnInitialize aufzurufen. Was ist wenn dein Destruktor oder sonstwas (unbewusst) noch etwas mit der MS-XML-Engine macht während du mit CoUnInitialize schon alles wieder abgebaut hast?

.. schön, dass Dir gruselig war.
CoInitialize habe ich nun im Constructor untergebracht
CoUnitialize habe ich nun im Destructor

So tut es.

TCodeSystemElement ist ein record
Die Liste eine generische Liste von TCodeSystemElement.

Vielen Dank.

Grüße
Klaus

generic 10. Nov 2020 11:27

AW: IXmlDocument wirft Exception
 
Entschärft sich das Problem nicht, wenn du
Delphi-Quellcode:
xmlDoc:=nil;
vor dem
Delphi-Quellcode:
Finally
einfügst?

Klaus01 10. Nov 2020 11:30

AW: IXmlDocument wirft Exception
 
Zitat:

Zitat von generic (Beitrag 1477024)
Entschärft sich das Problem nicht, wenn du
Delphi-Quellcode:
xmlDoc:=nil;
vor dem
Delphi-Quellcode:
Finally
einfügst?

.. ich hatte es es mal im finally vor CoUninitialze gesetzt - es hate aber keine Auswirkungen auf den Fehler.
Grüße
Klaus


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