2 Stimmen

Warum erkennt das "Leak"-Template von Instruments meinen Memory-Leak in meiner iOS-App nicht?

Ich tauche in die iOS-Entwicklung ein und mache mich mit den Tools vertraut. Am Ende jedes Tages führe ich ein "Ausführen mit Instruments-Tool -> Leaks" auf meiner App durch, um nach möglichen Memory-Leaks zu suchen, die ich an diesem Tag implementiert haben könnte. Es scheint nur selten irgendwelche Leaks zu erkennen und obwohl ich gerne denke, dass ich einfach ein natürlicher iOS-Programmierer bin, weigere ich mich das zu glauben ;)

Wie dem auch sei, ich habe gerade einen vermeintlichen Memory-Leak in meinem Code gefunden, der von Instruments nicht entdeckt wird. Ich habe diese Zeile Code...

gkSession = [[GKSession alloc] initWithSessionID:@"testID" displayName:@"Temp Display Name" sessionMode:GKSessionModeClient];

Und ich habe festgestellt, dass ich nirgendwo in meinem Code release aufrufe. Meine Fragen sind...

  1. Handelt es sich hierbei um einen Memory-Leak?
  2. Wenn ja, welche Gründe könnte es geben, warum Instruments es nicht erkennt?

Meine offensichtliche Sorge ist, dass ich Memory-Leaks in meinem Code habe und Instruments sie nicht erfasst.

Vielen Dank im Voraus für deine Hilfe!

6voto

Darron Punkte 20861

Es gibt mehrere Arten von dynamisch allokiertem Speicher.

  1. Speicher mit einem Referenzzähler größer als null, der immer noch referenziert wird und verwendet wird.

  2. Speicher mit einem Referenzzähler von null, der immer noch referenziert wird und verwendet wird.

  3. Speicher mit einem Referenzzähler größer als null, der nicht referenziert wird.

  4. Speicher mit einem Referenzzähler von null, der nicht referenziert wird.

  5. Speicher mit einem Referenzzähler größer als null, der immer noch referenziert wird, aber nicht verwendet wird.

Typ eins ist normal verwendeter Speicher. Typ zwei ist ein Fehler, der als illegaler Zugriff gemeldet wird, wenn versucht wird, auf die Referenz zuzugreifen. Typ 3 ist der Typ des Lecks, das von Instruments erkannt wird. Typ 4 sollte vom Speichersystem freigegeben werden.

Typ 5 ist ein Leck, das von Instruments nicht erkannt werden kann und auch nicht von einem vollständigen Garbage Collector behandelt wird. Dies scheint das zu sein, was du hast.

BEARBEITEN:

Ich habe Typ 6 vergessen - Speicher mit einem Referenzzähler, der nicht mit der tatsächlichen Anzahl von Referenzen übereinstimmt. Dies wird wahrscheinlich schließlich zu Typ 2 oder 4.

2voto

Steve Punkte 30188

Die Antwort auf #1 ist "vielleicht"... wenn Ihr Ansichtscontroller aus dem Stapel entfernt wird und niemand es anders beibehalten hat, sollte Ihr Ansichtscontroller freigegeben werden. Aber (und das könnte die Antwort auf Ihre Frage #2 sein) einer der Fehler, den ich ursprünglich gemacht habe, war nicht zu verstehen, dass der Navigationscontroller Ihren Ansichtscontroller behalten wird, wenn Sie pushViewController: aufrufen, sodass Sie es nicht müssen. Stellen Sie sicher, dass Sie Ihren Ansichtscontroller freigeben, nachdem Sie ihn erstellt und auf den Stapel gelegt haben.

MyViewController * viewController = [[MyViewController alloc] init...];
[self.navigationController pushViewController:viewController];
[viewController release];

Ich glaube, der statische Analysator wird Sie warnen, wenn Sie den Freigabeanruf in dieser Situation vergessen... das ist einer der Gründe, warum der statische Analysator so großartig ist.

Wenn Sie den Ansichtscontroller nicht an dieser Stelle freigeben, wird Ihr Behaltungszähler immer um +1 höher sein, als er sollte.

Ich habe bemerkt, dass der statische Analysator für diese Dinge viel nützlicher ist als das Leckwerkzeug der Instrumente. (Das zum Beispiel ein "Leck" nicht findet, das zirkuläre Verweise einschließt... zwei undichte Objekte, die sich selbst referenzieren, zeigen nicht auf, weil "ein Verweis" noch für Ihr Objekt vorhanden ist).

Also haben Sie derzeit etwas in der Art von...

@interface MyClass : UIViewController
{
     GKSession * gkSession;
}

...

@end

In Ihrer Implementierung sollten Sie sicherstellen, dass Sie Ihr iVar in Ihrer dealloc-Methode freigeben:

@implementation MyClass

...

- (void)dealloc
{
     [super dealloc];

     if (gkSession) [gkSession release];
}
@end

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X