I'm working on a Delphi wrapper for the Googledocs api using Delphi XE2. I generated all the classes using the XML Data Binding Wizard. This is a lot easier to explain using code, so here is the function my test calls.
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;
Now, at the point that 'end' is hit, Result.ChildNodes has an address in memory and it's count is 20. IXMLEntryTypeList is a child interface of IXMLNodeCollection.
Now here is my 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;
On the second if statement, I get an access violation saying "Access violation at address 0061A55C in module 'GoogleDocsApiTests.exe'. Read of address 00000049" and when I look at my watches for ReturnValue and ReturnValue.ChildNodes, I see that ReturnValue has the same address as Result did in the TGoogleDocsApi.GetEntries method, but it gives me the access violation on the watch for ReturnValue.ChildNodes and in the TGoogleDocsApi.GetEntires method, Result.ChildNodes has a valid address and its properties are filled out.
To me it looks like Delphi is releasing the ChildNodes property somewhere along the line, but that doesn't make sense to me since ReturnValue should still be referencing it which (I think) should keep it around.
Any ideas what might be going on?
ss
, but perhaps you simplified the code for this question. Also, what is keepingfeed
alive when the function returns. Does having taken a reference tofeed.Entry
keepfeed
alive? The answer will be along these lines, i.e. In the vein of what @hvd says. You have to keep the necessary objects alive. – David Heffernan