2014-04-30 10 views
5

Erstellen Sie ein neues ARC-Projekt und injizieren Sie diesen Code in didFinishLaunchingWithOptions.NSNumber mögliche Speicherleck

for (int i=0; i < 1000000; i++) { 
    NSNumber* num = [NSNumber numberWithInt:i]; 
    NSLog(@"%@", num); 
} 

NSLog(@"over"); 

Der Speicher der Anwendung wird zunehmen. Am Ende der for-Schleife wird auch der Speicher nicht verringert.

Wenn Sie jedoch in derselben for-Schleife ersetzen:

NSNumber* num = [NSNumber numberWithInt:i]; 

von

NSNumber* num = [[NSNumber alloc] initWithInt:i]; 

Dann Speicher stabil bleiben.

Ist dies ein erwartetes Verhalten?

EDIT:

Ok, also lassen Sie uns didFinishLaunchingWithOptions auf der Seite im Moment setzen. Sie können immer noch in ViewDidLoad und entfernen Sie eine Null, um das Ende der For-Schleife schneller Speicher der App wird bis zu ~ 11 MB wachsen. Wenn die for-Schleife endet, wird der Speicher NICHT abnehmen. Es bleibt bei ~ 11 MB.

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    for (int i=0; i < 100000; i++) { 
     NSNumber* num = [NSNumber numberWithInt:i]; 
     NSLog(@"%@", num); 
    } 

    NSLog(@"over"); 
} 

Wenn Sie gehen mit:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    @autoreleasepool { 
     for (int i=0; i < 100000; i++) { 
      NSNumber* num = [NSNumber numberWithInt:i]; 
      NSLog(@"%@", num); 
     } 
    } 

    NSLog(@"over"); 
} 

Überraschung! Überraschung! Sie werden das gleiche Verhalten haben. Sie werden ~ 11 MB erreichen und der Speicher wird nicht sinken. Das @autorelease in die Schleife zu setzen, funktioniert jedoch ... Aber hier versuche ich nicht, die Dinge zum Laufen zu bringen, sondern zu verstehen, warum am Ende der for-Schleife der Speicher nicht leer ist.

Also, Frage ist noch offen.

+0

Interessante .. Warten auf Spezialisten Meinungen zu diesem .. – rdurand

+0

Was passiert, wenn Sie setzen '@autoreleasepool {...}' 'um die for' Aussage? – trojanfoe

+0

Hast du es mit anderen Foundation-Klassen versucht? Was ist mit einer Init mit einem anderen Typ (initWithBool: zum Beispiel)? – rdurand

Antwort

3

Dies wird erwartet. Wenn Sie die NSNumber mit alloc/init zuweisen, wird ARC es freigeben, sobald es nicht mehr benötigt wird.

Wenn Sie es mit einer Komfortmethode wie numberWithInt: zuweisen, erhalten Sie ein Objekt, das in einem Autorelease-Pool zugeordnet ist. Bis der Autorelease-Pool leer ist, wird Ihr Speicher nicht freigegeben. Sie können jedoch einen Autofreigabepool für Ihre Schleife wie folgt erstellen:

for (int i=0; i < 1000000; i++) @autoreleasepool { 
    NSNumber* num = [NSNumber numberWithInt:i]; 
    NSLog(@"%@", num); 
} 

NSLog(@"over"); 

Dies sollte die Zahl frei nach jeder Iteration aussehen.

Sie können weitere Informationen erhalten Sie hier: Memory Management Policy

+1

Dies kann nicht der Grund sein. Der Haupt-Thread hat bereits einen Autorelease-Pool, der bei jedem Runloop-Hop geleert wird. Diese Nummern werden einen Moment nach dem 'application: didFinishLaunchingWithOptions:' beendet. – hamstergene

+0

@trjanfoe ja, wird es. – Jorge

+0

In der Tat. Ungewöhnliche Syntax jedoch. – trojanfoe