7

当我尝试使用DocumentElement. XMLDocumentXMLDocument根据某些文件的存在创建。

错误信息

项目 project1.exe 引发异常类 EAccessViolation,并带有消息“模块 'project1.exe' 中地址 0047B152 的访问冲突。读取地址 B1D59357”

我的代码

unit XMLBase;

interface
uses
  SysUtils, xmldom, XMLIntf, XMLDoc, Forms;

type
  TXMLbase = class
  private
    { Private declarations }
  public
    XMLDocument1: TXMLDocument;
    root: IXMLNode;    
    constructor Create;
  end;

var
  fn: string;

implementation

constructor TXMLbase.Create;
begin   
  fn := ChangeFileExt(Application.ExeName, '.xml');
  XMLDocument1 := TXMLDocument.Create(nil);
  XMLDocument1.Options := [doNodeAutoIndent];
  XMLDocument1.Active := False;
  //optional, is used to indent the Xml document
  if FileExists(fn) then
  begin
  XMLDocument1.LoadFromFile(fn);
  XMLDocument1.Active:= True;
  root := XMLDocument1.DocumentElement;  //<<--- Access Voilation
  end
  else
  begin
    XMLDocument1.Active := False;
    XMLDocument1.XML.Text := '';
    XMLDocument1.Active := True;
    root := XMLDocument1.AddChild('Settings');    
  end;
XMLDocument1.SaveToFile(fn);
end;

end.

访问冲突是由于对象或指针的不正确初始化引起的,这是否意味着XMLDocument没有被初始化?

4

2 回答 2

10

你正在传递nilTXMLDocument.Create. 执行此操作时,对象的行为类似于TInterfacedObject. 它的生命周期由接口引用计数管理。但是您没有持有对接口的引用。

文档对此进行了详细介绍。

在没有所有者的情况下创建 TXMLDocument 时,它的行为类似于接口对象。也就是说,当所有对其接口的引用都被释放时,TXMLDocument 实例被自动释放。但是,当使用 Owner 创建 TXMLDocument 时,它的行为与任何其他组件一样,并由其 Owner 释放。

如果启用 Debug DCU 并在其中设置断点,TXMLDocument.Destroy则可以观察到对象在访问冲突之前被销毁。

通过以下任一方式解决问题:

  1. 创建文档时传递所有者。
  2. 切换到使用接口来引用对象。即声明XMLDocument1IXMLDocument.

请确保您执行其中一项或多项,但不能同时执行两项!

于 2012-12-25T15:51:22.173 回答
3

正如大卫所说,只需将您的 XMLDocument1 声明从 更改为XMLDocument1: TXMLDocument即可XMLDocument1: IXMLDocument解决问题。您的问题与使用 TXMLDocument有关

于 2012-12-25T17:08:13.220 回答