2009-07-27 10 views
46

sigo obteniendo errores Clang en el siguiente tipo de código y no puedo averiguar por qué son erróneas o cómo resolverlos a satisfacción del Sonido metálico:Clang Error en "Deferencia nula potencial".

+ (NSString *)checkForLength: (NSString *)theString error: (NSError **)error { 
    BOOL hasLength = ([theString length] > 0); 
    if (hasLength) return theString; 
    else { 
     *error = [NSError errorWithDomain:@"ErrorDomain" code:hasLength userInfo:nil]; 
     return nil; 
    } 
} 

Dejando a un lado la naturaleza completamente artificial, de la ejemplo (que Clang objetó, por lo que es suficientemente ilustrativo), Clang rechaza la línea de asignación de error con la siguiente objeción:

Posible deferencia nula. De acuerdo con los estándares de codificación en 'Creación y devolución de NSError Objetos', el parámetro 'error' puede ser nulo.

Me gusta tener un informe prístino de Clang. He leído el documento citado y no veo la manera de hacer lo que se espera; Revisé algunas bibliotecas de código abierto de Cocoa y esta parece ser una expresión común. ¿Algunas ideas?

Respuesta

95

La forma de hacer lo que se espera se muestra en la lista 3-5 en ese documento. Con el ejemplo de código:

+ (NSString *)checkForLength: (NSString *)theString error: (NSError **)error { 
    BOOL hasLength = ([theString length] > 0); 
    if (hasLength) return theString; 
    else { 
     if (error != NULL) *error = [NSError errorWithDomain:@"ErrorDomain" code:hasLength userInfo:nil]; 
     return nil; 
    } 
} 
+1

Ugh, no puedo creer que me haya olvidado de eso. ¡Gracias! – bbrown

+0

Usé un millón de veces 'if (error) * error = ...' en su lugar, sin bloqueos ni errores/advertencias del analizador. ¿Puedo seguir así? –

+0

Sí, la equivalencia explícita de un puntero nulo a 0 y falso es algo objetivo C conservado de antiguo C. Pienso que es un estilo malo, pero sí puedes simplemente usar 'if (error)' si realmente quieres. –

16

La convención de cacao es que el valor de retorno debe indicar el éxito o el fracaso (en este caso, se vuelve cero en el caso de fallo) y el error es llenado con la información adicional, pero sólo cuando el la persona que llama lo solicita

En otras palabras

NSError *error = nil; 
NSString *result = [self checkForLength: aString error: &error]; 

y

NSString *result = [self checkForLength: aString error: NULL]; 

son dos formas válidas para invocar el método. Por lo tanto, el cuerpo del método siempre debe buscar un parámetro de error NULL:

if (error != NULL) 
    *error = ...; 
+0

En realidad, si el analizador estático clang no se queja de tu segundo snippit, enviaría un error :-) –

+0

¿Te refieres al fragmento donde se pasa NULL por el error? param? Este es un patrón documentado para usar NSError. Ver . –

+0

Si hubiera podido marcar dos respuestas, lo hubiera hecho. ¡Gracias por explicar el contexto en el que podría suceder! – bbrown