我正在使用Delphi XE2为Googledocs api开发一个Delphi包装器。我使用XML数据绑定(bind)向导生成了所有类。使用代码更容易解​​释,因此这是我的测试调用的函数。

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;

现在,在命中“end”的点上,Result.ChildNodes在内存中有一个地址,其计数为20。IXMLEntryTypeList是IXMLNodeCollection的子接口(interface)。

现在这是我的测试:
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;

在第二个if语句上,出现访问冲突,提示“模块'GoogleDocsApiTests.exe'中地址0061A55C的访问冲突。读取地址00000049”,当我查看ReturnValue和ReturnValue.ChildNodes的 watch 时,发现ReturnValue具有与Result在TGoogleDocsApi.GetEntries方法中使用的地址相同,但它给我带来了对ReturnValue.ChildNodes和TGoogleDocsApi.GetEntires方法的访问冲突,Result.ChildNodes具有有效地址,并且其属性已填写。

在我看来,Delphi似乎在沿线的某个地方释放ChildNodes属性,但这对我来说没有意义,因为ReturnValue仍应引用它(我认为)应该保留它。

任何想法可能会发生什么?

最佳答案

您正在使用TXMLDocument.CreateOwner调用nil。这意味着其生命周期是通过接口(interface)引用计数来控制的。为了使其正常工作,您需要实际使用接口(interface)。将xmlDoc的类型更改为IXMLDocument可以维护引用,否则VCL内部的某些内容会在您不希望使用它时将其释放。

关于Delphi似乎先破坏了对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10692899/

10-12 06:25