2012-05-21 14 views
8

Estoy trabajando en un contenedor Delphi para la API de Googledocs que usa Delphi XE2. Genere todas las clases usando el XML Data Binding Wizard. Esto es mucho más fácil de explicar usando código, así que aquí está la función que llama mi prueba.Parece que Delphi está destruyendo objetos antes de que sea

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; 

Ahora, al punto que 'fin' es golpeado, Result.ChildNodes tiene una dirección en la memoria y es el recuento es 20. IXMLEntryTypeList es una interfaz de niño IXMLNodeCollection.

Ahora aquí es mi prueba:

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; 

En la segunda sentencia if, consigo una violación de acceso diciendo "violación de acceso al 0061A55C dirección en el módulo 'GoogleDocsApiTests.exe' Read de dirección de 00.000.049." Y cuando Miro mis relojes para ReturnValue y ReturnValue.ChildNodes, veo que ReturnValue tiene la misma dirección que Result en el método TGoogleDocsApi.GetEntries, pero me da la infracción de acceso en el reloj para ReturnValue.ChildNodes y en el TGoogleDocsApi.GetEntires método, Result.ChildNodes tiene una dirección válida y sus propiedades se completan.

Para mí, parece que Delphi está liberando la propiedad ChildNodes en algún lugar de la línea, pero eso no tiene sentido para mí, ya que ReturnValue todavía debería hacer referencia a ella, lo que (creo) debería mantener.

¿Alguna idea de lo que podría estar pasando?

+5

Su función presenta 'ss', pero tal vez haya simplificado el código para esta pregunta. Además, lo que mantiene vivo a 'feed' cuando vuelve la función. ¿Ha tomado una referencia a 'feed.Entry' mantener' feed' vivo? La respuesta será en esta línea, es decir, en la línea de lo que dice @hvd. Tienes que mantener vivos los objetos necesarios. –

Respuesta

21

Llamas TXMLDocument.Create con Owner de nil. Eso significa que su vida útil se controla mediante el recuento de referencias de interfaz. Para que eso funcione, usted necesita para usar realmente las interfaces. Cambie el tipo de xmlDoc a IXMLDocument para mantener una referencia, o de lo contrario algo interno en la VCL lo liberará cuando no lo esté esperando.

+5

Guardar una referencia local antes de pasarla a una función también lo salvará de una libre prematura cuando usa parámetros const en llamadas a funciones: http://qc.embarcadero.com/wc/qcmain.aspx?d=90482 –

+4

+1, @nick, puede usar ['LoadXMLData'] (http://docwiki.embarcadero.com/Libraries/en/Xml.XMLDoc.LoadXMLData) para instanciar [' IXMLDocument'] (http://docwiki.embarcadero.com/ Libraries/en/Xml.XMLIntf.IXMLDocument). – TLama

Cuestiones relacionadas