2012-05-21 14 views
8

Ich arbeite an einem Delphi-Wrapper für die Googledocs API mit Delphi XE2. Ich habe alle Klassen mithilfe des XML-Datenbindungs-Assistenten generiert. Dies ist viel einfacher zu erklären mit Code, also hier ist die Funktion, die mein Test aufruft.Delphi scheint Objekte zu zerstören, bevor es sollte

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; 

nun an dem Punkt, dass ‚Ende‘ getroffen wird, hat Result.ChildNodes eine Adresse im Speicher und es ist ist 20. IXMLEntryTypeList ein Kind Schnittstelle von IXMLNodeCollection ist.

Hier ist mein Test:

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; 

Auf der zweiten if-Anweisung, ich eine Zugriffsverletzung zu sagen „Zugriffsverletzung bei Adresse 0061A55C in Modul‚GoogleDocsApiTests.exe‘Lesen von Adresse 00.000.049.“ Bekommen und wenn Ich schaue auf meine Uhren für ReturnValue und ReturnValue.ChildNodes, ich sehe, dass ReturnValue die gleiche Adresse wie Ergebnis in der TGoogleDocsApi.GetEntries-Methode hat, aber es gibt mir die Zugriffsverletzung auf die Uhr für ReturnValue.ChildNodes und in der TGoogleDocsApi.GetEntires method, Result.ChildNodes hat eine gültige Adresse und seine Eigenschaften sind ausgefüllt.

Für mich sieht es so aus, als ob Delphi die ChildNodes -Eigenschaft irgendwo entlang der Linie freigibt, aber das macht für mich keinen Sinn, da ReturnValue immer noch darauf verweisen sollte, was (denke ich) es behalten sollte.

Irgendwelche Ideen was passieren könnte?

+5

Ihre Funktion leckt "ss", aber vielleicht haben Sie den Code für diese Frage vereinfacht. Auch, was "feed" am Leben erhält, wenn die Funktion zurückkehrt. Hat "feed.Entry" einen Bezug auf "feed" genommen? Die Antwort wird in diese Richtung gehen, d. H. In die Richtung dessen, was @hvd sagt. Sie müssen die notwendigen Objekte am Leben erhalten. –

Antwort

21

Sie rufen TXMLDocument.Create mit einem Owner von nil. Das bedeutet, dass seine Lebensdauer über die Referenzzählung der Schnittstelle gesteuert wird. Damit das funktioniert, benötigen Sie , um tatsächlich Schnittstellen zu verwenden. Ändern Sie den Typ xmlDoc in IXMLDocument, um eine Referenz beizubehalten, sonst wird die VCL von einem internen Element befreit, wenn Sie es nicht erwarten.

+5

Wenn Sie einen lokalen Verweis beibehalten, bevor Sie ihn an eine Funktion übergeben, werden Sie auch vor vorzeitiger Freigabe geschützt, wenn Sie in Funktionsaufrufen die Parameter const verwenden: http://qc.embarcadero.com/wc/qcmain.aspx?d=90482 –

+4

+1, @nick, Sie können ['LoadXMLData'] (http://docwiki.embarcadero.com/Libraries/en/Xml.XMLDoc.LoadXMLData) verwenden, um [' IXMLDocument'] zu instanziieren (http://docwiki.embarcadero.com/ Bibliotheken/de/Xml.XMLIntf.IXMLDocument). – TLama

Verwandte Themen