【问题标题】:EXC_BAD_ACCESS with Objective-C Properties带有 Objective-C 属性的 EXC_BAD_ACCESS
【发布时间】:2010-11-14 14:06:58
【问题描述】:

在我的 iPhone 应用程序中,构造函数中有以下行:

self.myVar = myVar_in;

其中 myVar 是属性,myVar_in 是传递给构造函数的参数。

当我运行代码时,我在这一行收到 EXC_BAD_ACCESS 错误。但是,当我将行替换为:

[myVar release];
[myVar_in retain];
myVar = myVar_in;

代码运行良好。我的财产是这样声明的: NSNumber *myVar; ... @property (retain) NSNumber *myVar;

错误是一致的,我很肯定这不是变量范围问题。有人可以解释这种行为吗?

编辑:我已经确认 myVar_in 在行执行之前有效。这是实际的代码,虽然它没有多大帮助:

-(GetAddressRequestHelper*)initWithRequest:(ClientRequest*)request delegate:(id<ServerResponseDelegate>)delegate number:(NSNumber*)myVar_in location:(CLLocation*)location {
    self = [super initWithRequest:request delegate:delegate];

    if( self ) {
        // same behavior even if this line is uncommented!!!
        myVar_in = [NSNumber numberWithInt:123];

        // prints "myVar_in is 123"
        NSLog(@"myVar_in is %@",myVar_in);          

        // doesn't throw exception
        /*[myVar release];
          [myVar_in retain];
          myVar = myVar_in;*/

        // throws exception
        self.myVar = myVar_in;

        self.location=location;
    }
    return self;
}

EDIT2:我发现当我使用myVar_in = [NSNumber numberWithInt:123]; 显式初始化参数时,我仍然会遇到这种行为!

谢谢

【问题讨论】:

  • 作为一个小提示,最好在释放旧对象之前保留新对象,以防它们实际上是同一个对象。
  • @Quinn:谢谢,我忘记了。
  • @Quinn:完全正确,虽然我之前尝试过,但不适用于这种情况

标签: iphone objective-c cocoa cocoa-touch properties


【解决方案1】:

如果您的变量有@property 和@synthesize 语句,请尝试使用自动生成的setter 方法。这将确保 myVar_in 的值在分配给 myVar ([self setMyVar:myVar_in]) 时保留

您看到的错误可能是因为 myVar_in 在您使用时已释放。

【讨论】:

  • self.myVar 不这样做吗?我的印象是(我对 Objective-C 比较陌生)点表示法只是实际显式方法调用的别名。
  • @Blaenk 是正确的,点语法只是调用属性的 getter/setter 的一种漂亮方式,无论该方法是否合成。
【解决方案2】:

确保myVar_in 已实际初始化。您介意发布您初始化myVar_in 并调用初始化方法的代码吗?

【讨论】:

  • 如果 myVar_in 是一个实例变量,缺少初始化在某些情况下不会导致问题,但在其他情况下不会。毕竟,有效的代码所做的事情与综合设置器所做的事情几乎相同。不过,在调用站点设置断点并没有什么坏处……
  • 我知道你知道我对 Objective-c 很陌生,但他说“myVar_in 是传递给构造函数的参数”,据我所知,这不算作一个实例变量,但如果我错了,请告诉我。是的,代码和属性做同样的事情,这很奇怪!希望我们能尽快找到答案。我不禁认为这可能与myVar_in 有关,因为据说可以工作的“手动”代码与属性的作用相同。
  • Quinn Taylor:问题本身说myVar_in 是初始化方法的参数。
【解决方案3】:

此代码之间的一个关键区别:

[myVar release];
[myVar_in retain];
myVar = myVar_in;

还有这段代码:

self.myVar = myVar_in;

是使用self调用方法(setMyVar)。

几乎可以肯定,您的对象已被错误地创建/分配,并且 self 是一个随机值(在这种情况下,myVar = myVar_in 的分配是在随机内存上书写)。

发布显示您的对象创建/初始化调用的代码,以及如何衡量 myVar_in 如何获取其值。还要发布您的初始化代码(您可以(非常小心地)删除无关代码,但由于这是一个奇怪的情况,任何无关代码都可能是相关的......

【讨论】:

  • 现在我觉得自己像个白痴;我的超类初始化方法省略了“return self”行。我想念 Java :(
  • brainfsck:你应该从编译器那里得到一个警告(“控制到达非void函数的结尾”)。
  • 我愿意,但它被无用的“警告:'someVariable' 的本地声明隐藏实例变量”警告淹没了。我已经放弃询问如何禁用它们,因为不可避免地给了我一大堆“可变范围是非常危险的东西!甚至不要考虑禁用该警告!Apple 最清楚!”回复。
  • 摆脱这些警告很简单,brainfsck,只需以不同的方式命名局部变量和实例变量。那些编译器警告不是没用的。忽略它们是。
  • Eeek。这些警告不是没有用的!您确实希望将警告减少到由于编译器和/或库的记录问题引起的警告。相信我——我已经开发了 20 年,而且我经常在没有降落伞的情况下跳跃——但在这一点上,Apple 是对的——不要忽视警告。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-25
  • 2011-07-31
  • 2011-08-04
  • 1970-01-01
  • 2011-06-10
相关资源
最近更新 更多