2009-03-23 12 views
6

Tengo una aplicación de iPhone que recibe advertencias de memoria y por eso estoy tratando de encontrar fugas, hacer un uso más eficiente de la memoria, etc., con la ayuda de Instruments. Entre otras cosas, estoy tratando de eliminar cualquier objeto liberado automáticamente y reemplazarlo por objetos manuales alloc/init/release. Sin embargo, algunas llamadas API no parecen tener una versión 'init' (ver código a continuación). Yo ciertamente tengo algunos malentendidos básicos:Uso de fugas y objetos de instrumentos: ¿se cuentan los objetos liberados automáticamente como fugas?

  1. Si Me llamo en 'la API y vuelva objetos esencialmente autoreleased, estos objetos pueden aparecer como fugas en los instrumentos? Parece que veo este comportamiento en los instrumentos.

  2. Si es así a 2, ¿debería simplemente ignorar si no hay una alternativa de "no liberación automática" y estoy usando una API que necesito? Además, si este código se llama mucho, ¿debería reconsiderar por completo el algoritmo?

Aquí hay un código de utilidad de mi aplicación que se llama mucho. Básicamente determina si dos fechas son significativamente 'iguales'. Me he quedado en el código comentado para que pueda ver los tipos de mejoras que estoy buscando en mi base de código: esto redujo las fugas de memoria cuando funcioné en los instrumentos cuando comencé a crear manualmente NSDate (y lanzamiento) que ayudó. Sin embargo, todavía tengo los objetos componentes fecha que creo que se escapa ... pero es una llamada a la API (lo siento por el formato de código pero me parece que no puede mejorarlo en SO):

+ (BOOL)isDayEqualToDay:(NSDate*)date anotherDate:(NSDate*)anotherDate 
{ 

    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
    //NSCalendar *cal; 
    NSDateComponents *componentsFromDate, *componentsFromAnotherDate; 
    NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;  
    //cal = [NSCalendar currentCalendar]; 
    componentsFromDate = [cal components:unitFlags fromDate:date]; 
    componentsFromAnotherDate = [cal components:unitFlags fromDate:anotherDate]; 

    BOOL bDatesEqual = ([componentsFromDate year] == [componentsFromAnotherDate year] && 
         [componentsFromDate month] == [componentsFromAnotherDate month] && 
         [componentsFromDate day] == [componentsFromAnotherDate day]); 

    [cal release]; 

    return bDatesEqual; 

    /* 
    return (
     [componentsFromDate year] == [componentsFromAnotherDate year] && 
     [componentsFromDate month] == [componentsFromAnotherDate month] && 
     [componentsFromDate day] == [componentsFromAnotherDate day] 
    );*/ 
} 

pienso los componentsFromDate y los componentsFromAnotherDate se muestran como filtraciones, pero solo hay objetos devueltos esencialmente de una llamada a la API de NSData (liberados automáticamente). No estoy seguro de qué más podría hacer realmente para que esto sea más eficiente y estoy cuestionando mi comprensión de cómo usar mejor los instrumentos. Sugerencias?

Respuesta

4

El objeto liberado automáticamente no debería aparecer como una pérdida de memoria. En algún momento, las API tienen pérdidas de memoria en su interior. Debe presentar un informe de error con Apple. Las nuevas clases como NSCalendar y NSDateComponenets son especialmente sospechosas.

En cuanto a retención vs liberación automática, la regla general es que no importa a menos que esté en un círculo cerrado. En ese caso, si el ciclo cerrado va miles de veces sin que el evento se vaya, significa que nunca "limpia" el grupo de autorrelease.

3

Al usar cosas como GCD hay un grupo de autorrelease, pero no hay forma de saber cuándo (si alguna vez) se drena el grupo de autorrelease predeterminado. Si estás convencido de que los objetos liberados no se están liberando, asegúrate de que comprendes la API que estás utilizando. Si la memoria me sirve correctamente, las llamadas GCD (dispatch_async) clasifican las agrupaciones de liberación automática por usted, PERO el drenaje real de la agrupación puede tardar mucho tiempo. Por otra parte, NSOperations le permite hacer su propia agrupación de liberación automática.

He visto la detección de fuga de memoria en instrumentos que dependen de intervalos de 10 segundos como resultado advertencias de fuga de memoria falsa debido a un retraso prolongado antes de que se drenara un grupo de liberación automática. Así que trate de envolver del código en:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
... [your code] ... 
[pool drain]; 

me gustaría recomendar en contra de intentar reemplazar todos autoreleases con versiones manuales. El uso de la liberación automática da como resultado un recuento de llamadas retenidas/liberadas en un solo punto. Crear un objeto y luego volver a abrirlo automáticamente evita muchos errores de memoria, en mi opinión. Rápido, fácil. Se olvidará de liberar cosas al hacer uso de llamadas de liberación manual. Especialmente las condiciones de error son difíciles cuando se realizan lanzamientos manuales.

Haciendo una piscina sí mismo que da más control y durante la asignación de un trabajo intenso que a veces puede ser beneficioso para crear y vaciar sus propias piscinas. Pero como siempre, prueba y prueba, no hagas suposiciones.

+0

Parece que no hay forma de usar intstruments para depurar GDC. ¿Hay quizás otra forma? –

Cuestiones relacionadas