【问题标题】:autorelease makes my app crash自动释放使我的应用程序崩溃
【发布时间】:2011-03-15 17:11:49
【问题描述】:

此时我的应用程序有时会崩溃:

NSMutableData* position = [NSMutableData dataWithLength: 3 * sizeof(CGPoint)];

NSMutableData 调用自动释放时。

这是崩溃日志:

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x00000001, 0xe7ffdefe
Crashed Thread:  0

Thread 0 name:
Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   CoreFoundation            0x343dea60 _CFAutoreleasePoolAddObject + 136
1   CoreFoundation                0x343de9cc -[NSObject(NSObject) autorelease] + 8
2   Foundation                0x30c49166 +[NSMutableData(NSMutableData) dataWithLength:] + 34

你知道为什么吗?

更新: 变量“position”被返回并以这种方式使用:

    NSMutableData *positionData = [[SFinder sharedFinder] move:self.crId] ;
CGPoint *path = [positionData mutableBytes];
CGPoint location0 = path[0];

CGPoint location1 = path[1];

CGPoint location = path[2];

更新 2:

我使用 NSMutableData 删除了代码,但应用总是随机崩溃。在调试控制台上有一条消息:

*** attempt to pop an unknown autorelease pool (0x5830000)

堆栈:

Thread 0 Crashed:
   Dispatch queue: com.apple.main-thread
0   CoreFoundation               0x01348b69 _CFAutoreleasePoolPop + 201
1   UIKit                        0x008a947c _wrapRunLoopWithAutoreleasePoolHandler + 68
2   CoreFoundation               0x013edfbb __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 27
3   CoreFoundation               0x013830e7 __CFRunLoopDoObservers + 295
4   CoreFoundation               0x0134bbd7 __CFRunLoopRun + 1575
5   CoreFoundation               0x0134b240 CFRunLoopRunSpecific + 208
6   CoreFoundation               0x0134b161 CFRunLoopRunInMode + 97
7   GraphicsServices             0x029b3268 GSEventRunModal + 217
8   GraphicsServices             0x029b332d GSEventRun + 115
9   UIKit         0x008a942e UIApplicationMain + 1160
10  MyApp                        0x000029f4 main + 100 (main.m:13)
11  MyApp                        0x00002985 start + 53

【问题讨论】:

  • 你的意思是你自己调用自动释放?
  • @HyLian:看起来不像。查看堆栈跟踪。
  • 也许你自己在某个地方发布它?或者将其分配给您释放的另一个变量?
  • 代码在哪里?你知道当时是否存在自动释放池吗?
  • 如果您尝试自己分配/初始化它而不使用 auto 方法会怎样?

标签: iphone objective-c cocoa memory-management


【解决方案1】:

发现问题。 NSMutableData 存在问题。当您使用initWithLengthdataWithLength 初始化它并尝试通过mutableBytes 插入数据时会发生这种情况。当您插入最后一个字节时,它会在其他地方进行一些分配(即使该部分内存由其他对象拥有)导致EXC_BAD_ACCESS 和其他与内存相关的错误。所以用length+1个字节初始化就解决了问题。

【讨论】:

  • 分配内存不会导致EXC_BAD_ACCESS;访问您尚未分配的内存确实(这就是“错误访问”的意思)。听起来您正在创建长度小于复制到其中的数据;直接复制到数据的缓冲区不会导致它重新分配,因为对象无法知道您正在写入它的缓冲区,您正在写入的位置,或者您正在写入多少。如果您编辑问题以包含复制到数据中的代码,而不仅仅是从中复制出来的代码,这可能会有所帮助。
【解决方案2】:

当 NSMutableData 调用 自动释放。

??

它自己调用自动释放? 意义? 你用吗:

[position release];

[position autorelease];

如果是这样......好吧,不要这样做......你并不真的需要它,如果你只是用你在问题中编写的代码启动它......

【讨论】:

    【解决方案3】:

    您是否在任何其他代码中保留了变量“位置”?通常,如果您释放它,然后稍后 autoreleasepool 会被耗尽,从而在它不再存在时再次释放它。请see this post for possible details

    你也不应该让你的变量自己调用 autorelease(如果你是的话)。

    【讨论】:

      【解决方案4】:

      要么:

      1) 封闭的自动释放池有问题(它在哪里?是你自己定义的,还是默认的?)

      2) 有些东西在不应该的时候释放了你的NSMutableData* position。它在当前 NSAutoreleasePool 离开其范围之前执行此操作,将保留计数发送到 0 并导致调用 dealloc - 然后当自动释放池本身调用 release 时,您将崩溃,因为该对象已经被 dealloc 'd。

      【讨论】:

      • 我使用默认的自动释放池。变量“位置”被返回并用于其他方法,但我不保留或释放它。
      • 根据堆栈跟踪,在第一个异常中,对象甚至还没有返回——dataWithLength: 还没有返回。 最初尝试自动释放对象时发生异常。
      【解决方案5】:

      “位置”变量所指的对象会自动放入默认的自动释放池中,因为它源自 NSMutableData 便利方法。可能是默认的自动释放池不再有效。我只是在这里猜测。

      在任何情况下,默认自动释放池中的对象都保证仅在当前事件上下文的生命周期内保留。这可能与您所看到的有关。

      我建议您尝试将“位置”变量设置为具有“保留”属性的实例属性。这将使您更好地控制“位置”对象的生命周期。不要忘记在你的类的 dealloc 方法中释放“位置”对象。

      在我所有的 iOS 应用程序中,我严重依赖于由目标 C 框架提供的声明属性功能。如果我希望一个对象“停留”一段时间,我会使用带有属性“retain”的声明属性来引用它。然后我有一个更清晰的想法,即它究竟会保持多长时间。我也可以更好地控制它的生命周期。

      希望这会有所帮助。

      • 让大家知道

      【讨论】:

      • 如果在初始自动释放期间发生崩溃,将自动释放的对象分配给保留属性将无济于事。我同意似乎没有一个有效的池,但这没有任何意义;对象“只要当前事件上下文的生命周期”都是有效的,因为 UIApplication 会围绕每个事件的响应创建一个池,因此当您的代码在主线程上运行时应该始终有一个自动释放池。
      猜你喜欢
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多