EOutOfMemory使用Delphi创建大型XML

时间:2009-09-30 18:00:03

标签: xml delphi msxml

我正在使用Delphi从关系数据库中的数据创建XML文档。它使用小型数据集进行测试,但是当我尝试将数据集的大小扩展到生产级别时,它最终会在节点创建期间因EOutOfMemory异常而爆炸。

我正在使用表单上的TXMLDocument(MSXML作为供应商),我的代码通常如下所示:

  DS := GetDS(Conn, 'SELECT Fields. . . FROM Table WHERE InsuredID = ' +IntToStr(AInsuredID));

  try

    while not DS.Eof do
      with ANode.AddChild('LE') do
      begin
        AddChild('LEProvider').Text := DS.FieldByName('LEProvider').AsString;
        // Need to handle "other" here
        AddChild('Date').Text       := DateToXMLDate(DS.FieldByName('LEDate').AsDateTime);
        AddChild('Pct50').Text      := DS.FieldByName('50Percent').AsString;
        AddChild('Pct80').Text      := DS.FieldByName('80Percent').AsString;
        AddChild('Actuarial').Text  := DS.FieldByName('CompleteActuarial').AsString;
        AddChild('Multiplier').Text := DS.FieldByName('MortalityMultiplier').AsString;
        DS.Next;
      end;

  finally

    DS.Free;

  end;

使用此部分,以及应用于不同数据库表的许多其他类似构造的部分,执行多次。在此示例中,ANode是传递给函数的IXMLNode,用作容器。

我不希望磁盘上生成的XML文件超过10兆字节。我假设我在创建和处理XMLNodes时泄漏了内存,但我不熟悉Interfaces以了解如何追踪我的问题。

3 个答案:

答案 0 :(得分:3)

TXMDocument是一个DOM样式的界面,可以将整个文档保存在内存中。内存会以相当快的速度消耗掉。即使生成的文件不是那么大。你真的不需要TXMLDocument来写出一个简单的XML。为什么不直接写入xml格式的文件?

话虽如此:由于堆碎片或真正的内存泄漏,它也可能是一个错误。您可能想尝试这里提到的工具:Profiler and Memory Analysis Tools for Delphi

答案 1 :(得分:0)

每个AddChild调用都将其结果存储到编译器隐式声明的临时IXmlNode变量中。当前子程序返回时(无论是正常还是异常),它们应该自动清理。您可以通过声明自己的变量来使其生命周期更加明确。

var
  le, child: IXmlNode;
begin
  DS := GetDS(Conn, Format(Query, [AInsuredID]));
  try
    while not DS.Eof do begin
      le := ANode.AddChild('LE');
      child := le.AddChild('LEProvider');
      child.Text := DS.FieldByName('LEProvider').AsString;
      // Need to handle "other" here
      child := le.AddChild('Date');
      child.Text := DateToXMLDate(DS.FieldByName('LEDate').AsDateTime);
      child := le.AddChild('Pct50');
      child.Text := DS.FieldByName('50Percent').AsString;
      child := le.AddChild('Pct80');
      child.Text := DS.FieldByName('80Percent').AsString;
      child := le.AddChild('Actuarial');
      child.Text := DS.FieldByName('CompleteActuarial').AsString;
      child := le.AddChild('Multiplier');
      child.Text := DS.FieldByName('MortalityMultiplier').AsString;
      DS.Next;
    end;
  finally
    DS.Free;
  end;
end;

在上面的代码中,没有隐式接口变量。编译器会为每个AddNode调用声明一个新的隐式变量,但上面的代码表明只有两个是必需的,因为child可以为每个新的子节点重用。

但是,仅使用该代码不应导致极大的内存使用量。您似乎更有可能保留对您不再需要的对象的引用,或者您正在为某些接口对象创建循环引用。 MSXML库不应该创建自己的任何循环引用,但是您没有显示可能在此处运行的所有代码。

答案 2 :(得分:0)

尝试使用SAX解析器而不是DOM。 DOM将整个XML文件的表示保存在内存中。

尝试here

相关问题