Come posso risolvere questo avvertimento clang: “Oggetto con 0 conservano conta restituiti al chiamante in cui uno (possedere) mantenere il conteggio si aspetta”?
-
26-09-2019 - |
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?
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.