2011-01-10 13 views
5

Estoy desarrollando una aplicación de iPhone que utiliza principalmente la libreta de direcciones y la base de datos. Después de buscar unos 3000 contactos de la libreta de direcciones, adjunto etiquetas de cadena a los contactos (5 para cada uno). Estoy guardando mis etiquetas en la base de datos.Fugas de memoria causadas por CoreFoundation Framework

Para fines de prueba de carga he agregado 10.000 etiquetas a la aplicación. Pero durante la prueba de carga de mi aplicación, observé algunas pérdidas de memoria que no estaban relacionadas con el código de la Aplicación, pero representan un conjunto de conjuntos de instrucciones. También Instruments mostró Foundation como la biblioteca responsable de la pérdida (uso extensivo de NSString, NSDictionary, NSArray que pertenece al marco de Foundation). Mi aplicación se bloquea después de 10 a 15 minutos de uso. El informe de Crash menciona que la aplicación se bloqueó debido a la poca memoria.

La creación de perfiles de memoria con CLANG muestra cero fugas. ¿Cómo resuelvo estas fugas de memoria? ¿Estas fugas son las verdaderas culpables del accidente? ¿Hay otras herramientas disponibles para controlar fugas de memoria?

+1

Esto podría ser un problema de liberación automática. ¿Todavía sucede si lo haces en lotes? Es decir, en diferentes iteraciones del runloop? Tal vez envolver la operación con su propio grupo. – Eiko

+0

Sí, traté de drenar el grupo de versiones automáticas una vez que la aplicación recibe una advertencia de memoria, pero agotar el conjunto tampoco sirve. – Aditya

+0

Debe saber si las fugas son las culpables, ¿cuánta memoria dicen los instrumentos que está filtrando? – hooleyhoop

Respuesta

4

A menudo me parece que mis filtraciones dicen que están causadas por Core Foundation (o cualquier otro marco para ese asunto) pero son realmente mías. Con la excepción del simulador, rara vez encontrará fugas excesivas en los marcos.

Si abre el panel de detalles a la derecha en Instrumentos, puede encontrar los métodos de su aplicación allí. Eso le dará una indicación de dónde podría venir en su código. Una fuga puede provocar muchas otras filtraciones, y es posible que tenga que encontrar al culpable de nivel superior para deshacerse de las de menor nivel.

No debe esperar que Clang haga otra cosa que no sea encontrar las fugas más obvias. Es muy útil, pero eso es todo, solo una adición útil a la compilación.

-1

tratar de hacer algunos problemas en el código u: 1. Por favor, evite declaración esconderse como

NSString *string = [dictionary valueForKey:[dictionary2 valueForKey:@"something"]] 

código correcto es:

NSString *key = [dictionary2 valueForKey:@"something"]; 
NSString *string = [dictionary valueForKey:key]; 
key = nil; 
  1. Trate de evitar la declaración con autorelease y locales declaración como:

    NSArray * array = [NSArray array];

Si u hacer esto, asegúrese de que u tiene:

NSArray *array = [NSArray array]; 
.... some code where array is using; 
array = nil; 

mejor idea es alloc y liberar inmediatamente cuando u no es necesario objeto y ponerlo a cero. 3. Verifique si usa los ajustadores correctos. Probablemente, la mejor idea es evitar usarla, según mi experiencia, desasignar fugas de inicio de clase para getters y setters, que antes se usaban.

Si publica alguna parte del código u, donde puede ver la mayoría de las fugas (los instrumentos le dan la posibilidad de hacer clic en los objetos filtrados y ver el volumen de fugas en el código de programación) la comunidad puede sugerir más.

1

clang no es un comprobador de fugas. Solo detecta un pequeño subconjunto de problemas.

Para la depuración de fugas de memoria, debe centrarse en los instrumentos, específicamente los instrumentos de Asignación de objetos y fugas. Sin embargo, asegúrese de entender la diferencia entre las fugas y otras fuentes de uso de memoria alta.

Una vez que haya determinado que los objetos tienen filtraciones, use los instrumentos para examinar su seguimiento de la pila de asignación (para que pueda saber qué objeto es) y su historial de retención/liberación.

Si no es una filtración, entonces sugiero que investigue las instrucciones aquí: http: //www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak- using-heapshot-analysis-to-find-indeseable-memory-growth/

+0

Ya he resuelto todas las filtraciones causadas por el marco que pensé que se debían al framework, pero no lo estaban ... Así que ahora el problema es con las asignaciones ... hay muchísimas asignaciones hechas durante el ciclo de vida de la aplicación que causan que la aplicación se cuelgue después de 10 minutos de uso. – Aditya

+1

Las pilas son su amigo. – v01d

1

Lo más probable es que tenga un código que crea los objetos de la base. Leaks le muestra el lugar de asignación, pero eso generalmente se debe a una llamada realizada por su código para crear el objeto. Puede mirar la cadena de llamadas en Instruments y volver a lo largo de la cadena de llamadas hasta que llegue a su código: ese es el lugar donde está causando la asignación. Ahora, para esa asignación, fíjate en el manejo de tu memoria para ese objeto: ¿lo liberas un tiempo después?

Hay muchas formas en que puede dejar de liberar las propiedades de la memoria, por lo que sería difícil adivinar cuál podría estar golpeando. Las que veo cuando ayudo a las personas incluyen asignar un objeto y asignarlo a una variable de instancia a través de una propiedad con el atributo de retención, algo como esto:

@property (retain) NSString * myString;

...

self.myString = [[NSString alloc] initWithString: @ "foo"];

alloc + init crea un objeto retenido, el self.myString = incrementa el conteo retenido nuevamente. Si está codificado correctamente, el método dealloc libera la propiedad a través de uno de:

[myString release]; o self.myString = nil;

Y eso se encarga de retener agregado con el self.myString = pero NO se ocupa de retener desde la creación. Soluciones, UNA de las siguientes:

myString = [[NSString alloc] initWithString: @ "foo"]; // no llama al método setter para que no se retenga la asignación, pero no llama al setter, que podría ser malo si el setter no es trivial.

self.myString = [[[NSString alloc] initWithString: @ "foo"] liberación automática];

autorrelease libera alloc + init retener.

Ahora, por supuesto, este es un ejemplo artificial, ya que probablemente realmente utiliza:

self.myString = [NSString stringWithString: @ "foo"];

que es un método de clase que devuelve una cadena autorretratada y evita el problema. Pero la idea es mostrar un ejemplo simple para explicar este tipo de problema.

Hay muchas otras maneras de no liberar la memoria correctamente, pero el consejo de volver a subir la cadena de llamadas hasta que llegue a su código es la manera de ver dónde está activando la asignación de la memoria y luego puedes descubrir por qué no estás liberando eso correctamente.