2010-07-30 9 views
7

Hice la "Generación y análisis" en xCode y obtengo "Desreferencia de puntero nulo" al establecer una int normal en 0 en mi método init. Anoté en mi código a continuación para qué fila recibí el mensaje. Estoy desarrollando para iPhone.Desreferencia de puntero nulo, pero no estoy utilizando punteros

Bric.m

#import "Bric.h" 

@implementation Bric 

- (id)initWithImage:(UIImage *)img:(NSString*)clr{ 
    if (self = [super init]) { 
     image = [[UIImageView alloc] initWithImage:img]; 
    } 

    stepX = 0; //It's for this line I get the message 
    stepY = 0; 
    oldX = 0; 
    color = [[NSString alloc]initWithString:clr]; 
    visible = YES; 
    copied = NO; 
    return self; 
} 
@end 

Bric.h

#import <Foundation/Foundation.h> 

@interface Bric : NSObject { 

    int stepX; 
    int stepY; 

} 

-(id)initWithImage:(UIImage *)img:(NSString *)clr; 

@end 

No es el código completo, pegar lo que creo que es útil.

Como no estoy usando un puntero, esto me parece bastante extraño. ¿Cómo es que recibo este mensaje?

Gracias y saludos, Niklas

Respuesta

20

La primera instrucción if en su método init comprueba si [super init] devuelve nil o no. (Técnicamente debería escribirse if ((self = [super init])), que el nuevo compilador LLVM le advertirá).

El analizador estático comprueba TODAS las rutas de código posibles, incluso en el caso en que [super init] devuelve nulo. En este caso, su instrucción if falla y self es nil. Si self es nil, entonces sus variables de instancia no son accesibles.

Para solucionar esto, debe colocar sus inicializaciones dentro de la instrucción if con la inicialización de la imagen y luego return self fuera de la instrucción if.

+0

Gracias, ahora entiendo. Esto solucionó el problema. Supongo que no debería necesitar escribir "if ((self = [super init]))", usted acaba de escribir eso para reaons pedagógicos, rigth? Nunca he visto doble parátesis antes en ese lugar. – Nicsoft

+2

Los paréntesis dobles le dicen al compilador que evalúe el 'self = [super init]' primero y luego evalúe el resultado como un booleano después. Con el nuevo compilador LLVM, no tener doble paréntesis alrededor de una asignación en una instrucción 'if' generará una advertencia, porque el compilador está preguntando" inteligentemente "si se pretendía usar' == 'en lugar de' = '(que es un error común al hacer algo como 'if (x == 5)'. – Jasarien

0

¿Usted ha declarado como una propiedad? No estoy seguro si es necesario en este caso, pero no he hecho métodos de acceso (aunque creo que todavía se está ajustando la variable de instancia directamente ...)

es decir, en el archivo de cabecera,

@property int stepX; 

y en su archivo .m,

@synthesize stepX; 

Esto le permitirá acceder a la variable como self.stepX y self.stepY. A veces, el analizador comete errores ... Me di cuenta de que no se trata de while bucles de manera muy eficaz. De todos modos, mira lo que sucede si agregas esas líneas de código y me respondes.

+0

Gracias por su respuesta. Pero esto no ayudó, y dado que es un primitivo, no debería ser necesario si no me equivoco (nunca lo hice antes y nunca tuve un problema con eso). – Nicsoft

+0

En realidad, en mi experiencia, el analizador hace frente a los bucles while bastante bien. ¿Estás completamente seguro de que los problemas que marcó no eran reales? – JeremyP

+0

Bastante seguro. Era un ciclo "while not done" y decía que la variable "no hecho" (que se configuró en falso durante el ciclo) fue "configurada pero nunca leída". Disculpa por la publicación inútil. – Helen

0

Su método init es incorrecto.

Se debe tener este aspecto:

- (id)initWithImage:(UIImage *)img:(NSString*)clr 
{ 
    if (self = [super init]) // NB, this line should give you a waring 
    { 
     image = [[UIImageView alloc] initWithImage:img]; 
     stepX = 0; //It's for this line I get the message 
     stepY = 0; 
     oldX = 0; 
     color = [[NSString alloc]initWithString:clr]; 
     visible = YES; 
     copied = NO; 
    } 
    return self; 
} 

Asumo el mensaje que está recibiendo es del analizador estático. Como stepX es una variable de instancia, la línea

stepX = 0; 

es realmente la abreviatura de

self->stepX = 0; 

donde -> tiene su significado normal C.Como esa línea está fuera de la prueba, ese auto no es nulo en su código, el analizador estático está marcando un problema.

+0

Gracias por su respuesta. ¿Por qué debería recibir una advertencia en "if (self = [super init])"? No lo conseguí con mi código anterior y ninguno al usar los cambios que proporcionó ... La advertencia estaba en la primera fila después de la cláusula if, que está en la fila "stepX = 0;" en mi código publicado anteriormente. Supongo que es el camino para el analizador para decirme que step-row no debería estar allí (y yo junto con stackoverflow tengo que descubrir que debe estar dentro de la cláusula if ...). – Nicsoft

+0

Es una característica de seguridad para evitar escribir accidentalmente = cuando significa ==. Es posible que tengas esa advertencia apagada. – JeremyP

Cuestiones relacionadas