电话移动中的didAccelerate中的EXC_BAD_ACCESS

时间:2009-11-08 08:07:52

标签: iphone objective-c cocoa-touch

我正在做以下事情:

- (void) accelerometer: (UIAccelerometer *)accelerometer didAccelerate: (UIAcceleration *)acceleration {
if (self.lastAcceleration) {
    double i = self.lastAcceleration.x;

直到我实际倾斜手机才能正常工作。然后我在最后一行得到EXC_BAD_ACCESS。 lastAcceleration是一个带保留的属性。当我在调试器中查看“x”时,它具有较大的负值。为什么只会在倾斜时抛出EXC_BAD_ACCESS例外?

- 编辑(由于此答案适用于以下答复) -

我添加了这个,现在它可以工作:

- (void)dealloc {
[lastAcceleration release];

为什么会这么重要?还有,应该是

[self.lastAcceleration release];

我以前没有在任何地方发布过lastAcceleration。这是标题声明:

@interface MyViewController : UIViewController <UIAccelerometerDelegate> {
UIAcceleration *lastAcceleration;
}
@property(nonatomic, retain) UIAcceleration *lastAcceleration;
@end

3 个答案:

答案 0 :(得分:1)

我的预感是加速度计API与崩溃无关,你所显示的代码闻起来像是糟糕的内存管理,因为你混合了ivar和属性访问我怀疑你可能在其他部分做同样的事情你没有表现出来。

无论如何,这是一对最佳实践:

  • 你应该保留的任何对象中你有一个指针,相反,当你释放它时,你也应该删除指针,这样你就不会在它被解除分配后冒险访问它(这个规则的例外是一些模式,如委托对象,保留对象会导致保留周期,但这是一个完整的其他主题)
  • 通过@synthesized指令自动生成的ivar setter和getter将为你保留和释放对象,因为它看起来像是在分配一个指针,所以它们非常方便,但属性访问(self.something = ...)和ivar访问(某些东西= ......)不等同,所以你必须小心

确保不混淆两者的一个简单方法是做这样的事情:

@interface MyObject : NSObject
{
  SomethingObject *_something;
}

@property (nonatomic, retain) SomethingObject *something;

@end

@implementation MyObject

@synthesize something = _something;

@end

我们在这里做的是使ivar和属性名称略有不同,这样你就更清楚你正在使用哪一个,如果你使用的话,编译器会吠叫不使用bare {{1语法。

现在@ synthesize'd访问器是这样的:

something = ...

尽管如此,- (void)setSomething:(SomethingObject *)newSomething { [newSomething retain]; [_something release]; _something = newSomething; } - (SomethingObject *)something { return _something; } 是一件坏事,因为它还没有将lastAcceleration指针设置为nil,你不能保证它不会被释放,如果你不小心使用它你可能会崩溃。

[lastAcceleration release]不正确,因为访问者会为您处理所有保留/释放内容。

正确的做法是[self.lastAcceleration release];,如果查看访问者代码,将释放并将指针设置为nil。

可能发生的事情是你在某个地方释放lastAcceleration而没有将它设置为nil,并且self.lastAcceleration = nil;检查正在命中一个已发布的对象。

答案 1 :(得分:1)

保留属性的主要原因是避免显式保留/释放调用以及与之关联的内存管理错误。但是在dealloc方法中,无论哪种方式都很好,因为对象将很快停止存在。 [self.lastAcceleration release]; - 没必要。

[lastAcceleration release]; self.lastAcceleration = nil;

如果在dealloc中使用,两者都可以。 仅在dealloc之外使用

self.lastAcceleration = nil;

答案 2 :(得分:0)

访问已释放的内存时会引发

EXC_BAD_ACCESS。我的猜测是你在某个地方发布了self.lastAcceleration但没有将它设置为空。

你确定它与倾斜有关吗?