问题描述:
创建XML文档对象有时候失败。详细说明:
函数调用关系如下:
BuildLoginCommand               //创建登录的XML命令格式文本
┕━ BuildPackageRootNode    //创建XML格式的命令基本结构
         ┕━ NewXMLDoc        //创建XML文档对象在执行NewXMLDoc的时候,NewXMLDoc没有任何的参数,仅仅创建一个XML文档对象,然后返回而已。
然而,奇怪的问题出现了,在BuildLoginCommand方法的password参数为某些值的时候,创建对象后,可以看到Result的地址由nil变成一个内存地址,但是,执行下一步属性赋值操作的时候,产生了读写异常。导致程序不响应。例如:
password 的值 = 'cD?[2<HAWb1VH9-KFI<&+GN(XLO[!Kh' 时,会产生异常。
password 的值 = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh' 时,程序正常运行。var
  dm: TDataModule;//创建XML文档对象
function NewXMLDoc(): IXMLDocument;
begin
  if NOT Assigned( dm ) then
  begin
    dm := TDataModule.Create( nil );
  end;
  
  Result := TXMLDocument.Create( dm );  Result.Active := True;    //某些情况下,这儿会出错。产生EAccessViolation异常,然后程序就不响应了。
  Result.Version := '1.0';end;//创建XML格式的命令基本结构
function BuildPackageRootNode(cmdName: string): IXMLNode;
var
    doc : IXMLDocument;
    packageNode: IXMLNode;
    commandNode: IXMLNode;
begin
    doc := NewXMLDoc();
    //doc := NewXMLDocument();
    
    //创建Package根节点
    packageNode := doc.CreateNode('Package');
    //创建Command子节点
    commandNode := packageNode.AddChild('Command');
    commandNode.NodeValue := cmdName;
    //创建Body子结点
    packageNode.AddChild('Body');    Result := packageNode;
end;//创建登录的XML命令格式文本
function BuildLoginCommand(employeeId, password: string): string;
var
    packageNode :   IXMLNode;
    bodyNode    :   IXMLNode;
    employeeIdNode: IXMLNode;
    passwordNode :  IXMLNode;
begin
//password = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh'
    packageNode := BuildPackageRootNode( CMD_CLIENT_LOGIN );
    bodyNode := packageNode.ChildNodes['Body'];    employeeIdNode := bodyNode.AddChild('EmployeeId');
    employeeIdNode.NodeValue := employeeId;
    passwordNode := bodyNode.AddChild('Password');
    passwordNode.NodeValue := password;    Result := packageNode.XML;
end;

解决方案 »

  1.   

    XMLDocument1.Destroying
    XMLDocument1.Encoding 不知道行不
      

  2.   

    你的代码有点并发问题和内存泄漏..
    修改了一下,比较一下区别
    function BuildLoginCommand(employeeId, password: string): string;implementation
    //创建XML文档对象
    function NewXMLDoc(): IXMLDocument;
    begin
      Result := TXMLDocument.Create( nil);//不要为它弄个OWNER对象
      Result.Active := True;    
      Result.Version := '1.0';
    end;//创建XML格式的命令基本结构
    function BuildPackageRootNode(doc:IXMLDocument;cmdName: string): IXMLNode;
    var
        packageNode: IXMLNode;
        commandNode: IXMLNode;
    begin
        //创建Package根节点
        packageNode := doc.CreateNode('Package');
        //创建Command子节点
        commandNode := packageNode.AddChild('Command');
        commandNode.NodeValue := cmdName;
        //创建Body子结点
        packageNode.AddChild('Body');    Result := packageNode;
    end;//创建登录的XML命令格式文本
    function BuildLoginCommand(employeeId, password: string): string;
    var
        packageNode :   IXMLNode;
        bodyNode    :   IXMLNode;
        employeeIdNode: IXMLNode;
        passwordNode :  IXMLNode;    doc:IXMLDocument;
    const
      CMD_CLIENT_LOGIN='login';
    begin
    //password = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh'
        doc:=NewXMLDoc;    packageNode := BuildPackageRootNode(doc, CMD_CLIENT_LOGIN );
        bodyNode := packageNode.ChildNodes['Body'];    employeeIdNode := bodyNode.AddChild('EmployeeId');
        employeeIdNode.NodeValue := employeeId;
        passwordNode := bodyNode.AddChild('Password');
        passwordNode.NodeValue := password;    Result := packageNode.XML;
    end;
      

  3.   

    to halfdream(哈欠) :一旦改成你的方式之后,BuildPackageRootNode方法执行时出现灾难性故障。//创建Command子节点
    commandNode := packageNode.AddChild('Command');  //执行这句的时候出现灾难性故障。----------请问,我的代码的并发问题在哪儿?我怎么没看到呢?
    你是说的这个doc么?----------
    需要说明的是,令我最费解的是,我的代码中
    password 的值 = 'cD?[2<HAWb1VH9-KFI<&+GN(XLO[!Kh' 时,总是会产生异常。
    password 的值 = 'cD?Nnl6%*waT,`~C-}p($:{h|I-s4@!Kh' 时,程序一直正常运行。创建 IXMLDocument 对象的时候,怎么会受这个 password 的值影响了?
      

  4.   

    function NewXMLDoc(): IXMLDocument;
    begin
      if NOT Assigned( dm ) then
      begin
        dm := TDataModule.Create( nil );
      end;
      
      Result := TXMLDocument.Create( dm );  Result.Active := True;    //某些情况下,这儿会出错。产生EAccessViolation异常,然后程序就不响应了。
      Result.Version := '1.0';end;
    -----------------------
    Result.Active := True; //这里就是 password 的值等于某些值的时候,引起的EAccessViolation异常,当时程序不响应。
      

  5.   

    我改了主要有这样几处:1,NewXMLDoc()中去掉了数据模块的创建..
      Result := TXMLDocument.Create( dm );//这样创建的XMLDOCUMENT你什么是去释放呢?于是,我将其改为
    Result := TXMLDocument.Create( nil);//
    当然,只改这一处地方是不行的...看接下来第2点:
    2,function BuildPackageRootNode(cmdName: string): IXMLNode;
    var
        doc : IXMLDocument;//楼主这儿是个局部变量来引用XMLDOC这儿是接着必须修改的地方.
    当这个函数返回时,也就是在BuildLoginCommand函数这一层中,
    doc变量会被释放...这就影响到XmlDocument对象的生存期.
    于是我整理了一下楼主的代码,让TXMLDOCUMENT对象的创建与释放简单明显化些.
    改在BuildLoginCommand中创建XMLDOCUMENT对象.
      

  6.   

    to halfdream(哈欠):搞定了,谢谢。把函数声明 BuildPackageRootNode(doc:IXMLDocument;cmdName: string): IXMLNode;
    改成       BuildPackageRootNode(var doc:IXMLDocument;cmdName: string): IXMLNode;
    就好了,不然还是灾难性故障,doc还是什么都没有。我是做C#的,偶然用一下Delphi写客户端的WindowsForm,没想到这么不习惯。
    按照我的思维,BuildPackageRootNode 返回的是 packageNode,如果他的 parent 是这个方法中的局部变量,存在一个引用关系也不会消失,所以说它的parent也不该消失才对。应该不会存在你所说的生存周期才对呀?直到对packageNode的引用为0,释放资源的时候,才会释放你所说的doc啊!
      

  7.   

    主要是TXMLDocument这个东西封装得比较特别..呵呵.
      

  8.   

    事实证明,我曾经的写法是没有问题的,问题出在调用的外部一个DLL中的函数中,存在内存泄漏问题.所以导致了这以奇怪的问题.
      

  9.   

    有没有不创建IXMLDocument,直接创建IXMLNode的方法