Come posso risolvere questo avvertimento clang: “Oggetto con 0 conservano conta restituiti al chiamante in cui uno (possedere) mantenere il conteggio si aspetta”?

StackOverflow https://stackoverflow.com/questions/2837904

Domanda

Ho un pezzo di codice Objective-C, che è simile al seguente:

- (NSString *)copyData:(NSData *)data
{
    NSString *path = [[[self outputDirectory] stringByAppendingPathComponent:@"archive"] stringByAppendingPathExtension:@"zip"];
    NSLog(@"Copying data to %@", path);
    [data writeToFile:path atomically:NO];
    return path;
}

Il codice viene chiamato da un inizializzatore che assomiglia a questo:

- (id)initWithData:(NSData *)data
{
    if ((self = [super init]) != nil) {
        NSString *path = [self copyData:data];        // Line 41 (referenced in warning, shown below)
        return [self initWithContentsOfFile:path];
    }
    return self;
}

Quando si esegue l'analizzatore clang statica, ottengo le seguenti avvertenze per la variabile path:

  

potenziale perdita di un oggetto allocato sulla linea 41 e memorizzati in 'percorso'

     

Oggetto con +0 mantenere i conteggi restituiti al chiamante in cui uno (possedere) mantenere il conteggio è previsto

Sono confuso. La mia comprensione è che stringByAppendingPathComponent deve restituire una stringa autoreleased, in modo che dovrebbe avere una rete conservare conteggio di 0. (Ovviamente non mi voglio per conservarlo.)

Ho cercato alterazione copyData: di restituire quanto segue, ma non ha sbarazzarsi di avvertimento:

return [[path retain] autorelease];

Allora, qual è il problema con questo avvertimento?

È stato utile?

Soluzione

Ho il sospetto è solo notando un metodo con il copy prefisso e segnalando che come qualcosa che dovrebbe restituire qualcosa che il chiamante possiede, perché pensa che è seguito cacao convenzioni di denominazione.

Nel tuo caso, ovviamente, si fa riferimento a file e quant'altro, quindi è un avvertimento ignorabile. Se si cambia il nome del metodo, a qualcosa come saveData: invece, scommetto che l'avviso andrà via.

Altri suggerimenti

Inoltre, per i tempi in cui davvero si vuole nominare un metodo con 'copia' o qualcosa perché a prescindere dalla linee guida di gestione della memoria di cacao, la copia è il nome migliore per il metodo, è possibile annotare il metodo declairation con NS_RETURNS_NOT_RETAINED e poi Clang non ti darà un avvertimento. Quindi:

// Copies data from data to string; does not follow the copy rule
- (NSString*)copyData:(NSData*)data NS_RETURNS_NOT_RETAINED;

Dato che il metodo ha il nome copy in esso, l'analizzatore si aspetta l'oggetto restituito avere un +1 conservare conteggio, secondo la Guida Memory Management .

No, questo non è corretto; a meno che il metodo contiene "alloc", "copia", "nuovo", o di una delle altre parole chiave che implica l'oggetto sarà di proprietà del invoker, il metodo restituisce un oggetto autoreleased o comunque gestito, in modo stringByAppendingPathComponent sta tornando una stringa autoreleased .

In cima a quello, il metodo "CopyData", contiene la parola "copia", il che implica che il risultato dovrebbe essere di proprietà (e rilasciato) dal chiamante. Tuttavia, il risultato che è stato restituito autoreleased, da qui il messaggio di errore che vi dà. Se si vuole correggere l'errore, non autorelease. Cioè:

 return [path retain]

Certo che implica che i chiamanti della vostra funzione necessità di rilasciarlo. In alternativa, è possibile modificare il nome della funzione in modo che sia conforme con le linee guida di gestione della memoria.

Il nome "CopyData", IMHO, è comunque poco intuitivo. Vorrei suggerire di rinominare la funzione di "pathToSavedDataWithData" o simili. Qualcosa che dice ciò che effettivamente sta facendo.

ho intenzione di prendere una pugnalata a questo e immaginare che si otterrebbe lo stesso messaggio di errore esatto, se non il nome della vostra routine iniziato con "copia ..." o no. Ho appena finito in uno scenario simile e "copia" non era parte del nome della routine mi stava chiamando. Clang stava dando il messaggio di errore, semplicemente perché stavo tornando un oggetto autoreleased, una situazione pericolosa. Fare la

  return [path retain]  

trick alla fine come raccomandato da Michael prese cura del problema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top