空指针解引用,但是我没有使用指针

7
我在xCode中进行了“构建和分析”,在我的初始化方法中将一个普通的int设置为0时,出现了“空指针解引用”的错误。我在下面的代码中注明了出错的行数。我正在开发iPhone应用。
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

这不是完整的代码,我只粘贴了我认为有用的部分。

既然我没有使用指针,我觉得这很奇怪。为什么我会收到这个消息?

谢谢和问候, 尼克拉斯

3个回答

20
你的init方法中第一个if语句是在检查[super init]是否返回nil。(严格来说应该写成if ((self = [super init])),这会被新版本的LLVM编译器警告)。
静态分析器正在检查所有可能的代码路径,即使是[super init]返回nil的情况。在这种情况下,你的if语句失败了,selfnil。如果selfnil,那么它的实例变量就是不可访问的。
为了解决这个问题,你需要将初始化放在带有图像初始化的if语句内部,然后在if语句外部使用return self

谢谢,我现在明白了。这解决了问题。我猜我不需要写 "if ((self = [super init]))",你只是为了教学目的而写的,对吧?我从来没有在那个地方看到过双括号。 - Nicsoft
2
双括号告诉编译器先评估 self = [super init],然后将结果作为布尔值进行评估。使用新的LLVM编译器,在if语句中没有双括号的赋值会生成一个警告,因为编译器会“智能地”询问您是否意味着使用 == 而不是 =(当执行类似于 if (x == 5) 的操作时,这是一个常见的错误)。 - Jasarien

0
你是否将它声明为属性?我不确定在这种情况下是否必要,但你没有创建访问器方法(尽管我认为你仍然直接设置实例变量...)
也就是说,在你的头文件中,
@property int stepX;

在你的 .m 文件中,

@synthesize stepX;

这将允许您访问变量self.stepX和self.stepY。但有时分析器会出错...我注意到它不能很有效地处理while循环。无论如何,如果您添加这些代码并回复我,我们可以看看会发生什么。


谢谢你的回答。但是这并没有帮助到我,而且由于它是一个原始类型,如果我没有弄错的话,它不应该是必需的(至少以前从来没有这样做过,也从来没有遇到过这样的问题)。 - Nicsoft
实际上,根据我的经验,分析器对while循环的处理相当不错。你确定它标记的问题都不是真实存在的吗? - JeremyP
非常确定。这是一个“while not done”循环,并且它说“not done”变量(在循环期间设置为false)被“设置但从未读取”。对于那个无用的帖子感到抱歉。 - Helen

0
你的初始化方法有误。
应该像这样写:
- (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;
}

我猜你收到的消息是来自静态分析器。由于stepX是实例变量,所以这一行

stepX = 0;

实际上是...的简写

self->stepX = 0;

->在这里有其正常的C语言含义。由于该行代码不在测试self非空的范围内,静态分析器会标记一个问题。


谢谢你的回答。为什么在“if (self = [super init])”处会收到警告?我以前的代码没有这个问题,使用你提供的更改也没有出现这个问题...警告出现在if语句后的第一行,也就是我上面发布的代码中的“stepX = 0;”行。我猜这是分析器告诉我stepX行不应该在那里(我和stackoverflow需要找出它应该在if语句内部...)。 - Nicsoft
这是一项安全功能,用于防止在您想要使用“==”时意外输入“=”。您可能已经关闭了该警告。 - JeremyP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接