2012-05-21 6 views
8

私はDelphi XE2を使ってGoogledocs APIのDelphiラッパーを開発しています。 XMLデータバインディングウィザードを使用してすべてのクラスを生成しました。これはコードを使って説明するのがはるかに簡単なので、ここでは私のテストが呼び出す関数です。Delphiはオブジェクトを破壊するようです。

function TGoogleDocsApi.GetEntries : IXMLEntryTypeList; 
var 
    httpHelper : IHttpHelper; 
    xml, url : string; 
    xmlDoc : TXmlDocument; 
    ss : TStringStream; 
    feed : IXmlFeedType; 
begin 
    ss := TStringStream.Create; 
    httpHelper := THttpHelper.Create; 
    if(fToken.IsExpired) then 
    fToken.Refresh(fClientId,fClientSecret); 
    url := BaseUrl + 'feeds/default/private/full?showfolders=true&access_token='+fToken.AccessToken+'&v=3'; 
    xml := httpHelper.GetResponse(url); 
    ss.WriteString(xml); 
    ss.Position := 0; 
    xmlDoc := TXmlDocument.Create(nil); 
    xmlDoc.LoadFromStream(ss); 
    feed := GoogleData2.Getfeed(xmlDoc); 
    Result := feed.Entry; 
end; 

は今、「末端が」ヒットされた時点で、Result.ChildNodesは、メモリ内のアドレスを持っており、それはカウントが20 IXMLEntryTypeListがIXMLNodeCollectionの子インタフェースであるのです。今ここに

は私のテストで:もし番目のステートメントで

procedure TestIGoogleDocsApi.TestGetEntries; 
var 
    ReturnValue: IXMLEntryTypeList; 
begin 
    ReturnValue := FIGoogleDocsApi.GetEntries; 
    if(ReturnValue = nil) then 
    fail('Return value cannot be nil'); 
    if(ReturnValue.ChildNodes.Count = 0) then 
    fail('ChildNodes count cannot be 0'); 
end; 

、私は言って、アクセス違反取得したときに、「モジュールのアドレス0061A55Cでアクセス違反 『GoogleDocsApiTests.exe』のアドレス00000049の読み取り。」 ReturnValueとReturnValue.ChildNodesの時計を見ると、ReturnValueはTGoogleDocsApi.GetEntriesメソッドのResultと同じアドレスを持っていますが、ReturnValue.ChildNodesとTGoogleDocsApi.GetEntiresのウォッチでアクセス違反が発生しますメソッドでは、Result.ChildNodesに有効なアドレスがあり、そのプロパティが記入されています。

DelphiがChildNodesプロパティをラインに沿ってどこかにリリースしているようですが、ReturnValueはそれを参照する必要があるので、私には分かりません。

何が起こっている可能性がありますか?

+5

あなたの関数は 'ss'をリークしますが、おそらくあなたはこの質問のコードを単純化しました。また、関数が返ってきたときに 'feed 'を生きているものにしています。 'feed.Entry'への参照を取り、' feed'を生きたままにしていますか?答えはこれらの行に沿っています。すなわち、@ hvdの言うところの静脈にあります。必要なオブジェクトを生かしておく必要があります。 –

答えて

21

Ownernilの場合は、TXMLDocument.Createと発声しています。つまり、その寿命はインタフェース参照カウントによって制御されます。そのためには、実際にインターフェイスを使用するにはが必要です。 xmlDocのタイプをIXMLDocumentに変更して参照を維持してください。そうしないと、VCL内部の何かが期待していないときに解放されます。

+5

関数に渡す前にローカル参照を保持することで、関数呼び出しでconstパラメータを使用するときの早すぎる解放を防ぐことができます。http://qc.embarcadero.com/wc/qcmain.aspx?d=90482 –

+4

+1、 @nickでは、['LoadXMLData'](http://docwiki.embarcadero.com/Libraries/en/Xml.XMLDoc.LoadXMLData)を使って[' IXMLDocument']をインスタンス化することができます(http://docwiki.embarcadero.com/ライブラリ/ ja/Xml.XMLIntf.IXMLDocument)。 – TLama

関連する問題