2014-04-30 28 views
5

Creare un nuovo progetto ARC e inserire questo codice in didFinishLaunchingWithOptions.NSNumero possibile perdita di memoria

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

NSLog(@"over"); 

La memoria dell'applicazione aumenterà. Inoltre, alla fine del ciclo for, la memoria non diminuirà.

Tuttavia, se si sostituisce nello stesso ciclo for:

NSNumber* num = [NSNumber numberWithInt:i]; 

da

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

Poi memoria rimarrà stabile.

È un comportamento previsto?

EDIT:

Ok, mettiamola didFinishLaunchingWithOptions sul lato per il momento. Puoi ancora visualizzare viewDidLoad e rimuovere uno zero per raggiungere la fine del ciclo più veloce La memoria della app aumenterà fino a ~ 11 MB. Quando termina il ciclo for, la memoria NON diminuirà. Resta a ~ 11 MB.

- (void)viewDidLoad { 
    [super viewDidLoad]; 

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

    NSLog(@"over"); 
} 

Se si va con:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

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

    NSLog(@"over"); 
} 

Sorpresa! Sorpresa! Avrai lo stesso identico comportamento. Raggiungerai ~ 11 MB e la memoria NON diminuirà. Tuttavia, mettere @autorelease all'interno del ciclo funzionerà ... Ma qui, non sto cercando di far funzionare le cose, ma capisco perché la memoria non viene svuotata alla fine del ciclo for.

Quindi, la domanda è ancora aperta.

+0

interessante .. In attesa di specialisti opinioni su questo .. – rdurand

+0

Che cosa succede se si mette '@autoreleasepool {...}' intorno alla dichiarazione 'for'? – trojanfoe

+0

Hai provato con altre classi Foundation? Che dire di un init con un altro tipo (initWithBool: ad esempio)? – rdurand

risposta

3

Questo è previsto. Quando si assegna lo NSNumber con alloc/init, ARC lo svincolerà non appena non sarà più necessario.

Quando lo si assegna con un metodo di convenienza come numberWithInt: ciò che si ottiene è un oggetto allocato in un pool di autorelease. Fino a quando il pool di autorelease non viene scaricato, la memoria non verrà liberata. Tuttavia, è possibile creare un pool autorelease per il ciclo come questo:

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

NSLog(@"over"); 

Questo dovrebbe liberare il numero dopo ogni look iterazione.

È possibile ottenere ulteriori dettagli qui: Memory Management Policy

+1

Questo non può essere il motivo. Il thread principale ha già un pool di autorelease, che viene scaricato su ogni hop di runloop. Questi numeri saranno liberati un momento dopo l'applicazione: didFinishLaunchingWithOptions: 'exit. – hamstergene

+0

@trojanfoe sì, lo farà. – Jorge

+0

Infatti. Sintassi insolita, però. – trojanfoe