XMLベースでプロトコル定義を構築するためにDelphi 7 XMLDocユニットを使用しています。つまり、プロトコルはXMLファイルで定義されており、一部のオブジェクトはこのXMLから情報を取得して、TCP / IPで配信されるISO8583メッセージを分解および構築します。IXMLDocument
とIXMLNode
インターフェースを広く利用しています。すべて問題なく、終了時点で (FASTMM を使用して) メモリ リークはありません。しかし、実行中、ソフトウェアはゆっくりとメモリを消費します。TXMLDocument
XMLアクセスに使用しているオブジェクト(派生元)を解放すると、メモリが何らかの形で解放されます。IXMLDocument
私が分析したところ、IXMLNode
インターフェイスを使用しなければメモリの問題はないことがわかりましたが、もちろん使用する必要があります。
TXMLTree
から派生したオブジェクト ( ) がありますTXMLDocmument
。
TXMLTree = class(TXMLDocument, IXMLDocument)
...
end;
別のオブジェクト ( TDPR
) があり、そのコンストラクターでインターフェイス ( ) とドキュメントの開始点へのインターフェイス ( ) を作成TXMLTree
して取得します。fIDocument
fIDocStart
TDPR = class(TObject)
...
fIDocument:IXMLDocument;
fIDocStart:IXMLNode;
...
end;
constructor TDPR.Create(aFilename: string);
begin
inherited;
...
fTree := TXMLTree.Create(aFilename);
fTree.GetInterface(IXMLDocument, fIDocument);
fIDocStart := fIDocument.DocumentElement;
...
end;
通常、XML ドキュメントに到達するための出発点としてfIDocument
andを使用しfIDocStart
、次のようなコードを記述します。
node := fIDocument.DocumentElement.ChildNodes[aName].ChildNodes.FindNode(aFieldName);
また
node := fIDocStart.ChildNodes[aName].ChildNodes.FindNode(aFieldName);
そのような行は 1 行だけでゆっくりとメモリ使用量を増やすのに十分ですがfor
、たとえば 1000 万のループでそれを実行すると、それ以上の効果はありません。
それではFoo
、ドキュメントの開始点を取得する手順を見てみましょう。
procedure TDPR.Foo;
var lNode:IXMLNode;
begin
lNode := IDocument.DocumentElement;
end;
このプロシージャを呼び出すと、メモリ使用量が少し増加しますが、定期的に呼び出すと、メモリが不足するのは時間の問題です。
ただしfIDocStart
、必要なインターフェイスを既に格納している whichを使用するとDocumentElement
、何度も呼び出す必要がなくなり、メモリの問題は発生しません。
procedure TDPR.Foo;
var lNode:IXMLNode;
begin
lNode := fIDocStart;
end;
そのため、インターフェイス オブジェクト (など) を取得して返すすべての呼び出しでは、IXMLDocument
IXMLNode
IXMLNodeList
メモリが割り当てられ、参照オブジェクトが適切に解放されている間はメモリが解放されないようです。同じノードを要求しても。もちろん、メモリを使い果たすのを避けるためだけに、考えられるすべてのノードを保存することはできません。
のデストラクタでは、対応するインターフェイスを に設定してTDPR
解放し、終了時にメモリ リークは検出されません。参照カウンターは問題ないようです。TXMLTree
nil
destructor TDPR.Destroy;
begin
...
fIDocStart := nil;
fIDocument := nil;
...
inherited;
end;
XML
また、大きなファイルとは関係ありません。問題は次のXML
ように同じです。
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl"?>
<Base24-POS>
<Instructions>
<Parameters Receive="1"/>
</Instructions>
</Base24-POS>
私はそれが不明瞭であることを知っており、誰かがすでに同じ問題に遭遇し、解決策を見つけた可能性があることを願っています. (ところで、私はWindowsXPでまったく同じコードを問題なく使用したことを覚えています。現在はWindows7です)