【问题标题】:Cannot find over-released object debugging on device在设备上找不到过度释放的对象调试
【发布时间】:2011-10-22 20:50:06
【问题描述】:

我有一个相当大的应用程序,它在模拟器中工作,但在 iPhone 设备上的过度发布对象场景中创建。 NSzombies 似乎是要走的路线,除了该对象在模拟器上没有过度释放并且 NSZombies 在设备上不起作用。经过数小时的日志记录,我似乎能够将它固定在我跑步之间的某个地方 -

[locManager startUpdatingLocation] 和开始 -

(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation

这解释了为什么它可以在模拟器上运行,我没有检测到定位能力并且不运行该定位代码。

当我在 [locManager startUpdatingLocation] 之前和之后在线 NSLog 时,我的 NSString 对象被分配并存在。但是当应用程序执行并点击 locationManager: NSLog 显示 NSString 已被释放,消失了。这个字符串对象与位置处理或功能完全无关。不相关的 NSString。我已经注释掉了所有其他潜在的活动,并注释掉了所有明确的发布代码,但找不到它发生的时间。

我更沮丧的是 lldb 似乎不支持观察点而 gdb 支持它们,但这个版本似乎它们不起作用! gdb 将设置一个硬件观察点,然后 Xcode 说它正在运行,但 30 分钟后仍然没有视觉活动或中断。

我正在使用 Lion、Xcode 4.1.1 和太多咖啡。

我应该采取什么方法在如此狭窄的活动范围和有限的工具中找到这个已发布的 NSString 对象?

【问题讨论】:

  • CoreLocation 模拟器可以让你在 iPhone 模拟器上使用 CL。您也许可以通过这种方式在 iPhone 模拟器上复制该问题。请参阅 SO 上的testing-corelocation-on-iphone-simulator

标签: iphone ios gdb watchpoint xcode4.1


【解决方案1】:

曾几何时,我有一个复杂的情况来定位释放的对象,所以我只是从这个对象继承到 MyObject 并以以下方式覆盖保留和释放:

这里是 DebugString.h 文件:

#import <Foundation/Foundation.h>

@interface DebugString : NSString

@end

这里是 DebugString.m 文件:

#import "DebugString.h"

@implementation DebugString

- (id) retain {
    NSLog(@"%i", [self retainCount]);
    return [super retain];
}

- (void) release {
    NSLog(@"%i", [self retainCount]);
    [super release];
}

@end

我在这个方法中设置了一个断点,并在我预计会崩溃的阶段打开它们。之后我才开始一个一个地处理这个电话,发现了一个问题。它很复杂,但有时可能会有所帮助,而且我从未在论坛中看到过这种方法。也许它也会帮助你。

【讨论】:

  • Nikita,这是一个有趣的方法。所以我会将这两种方法放在存在问题的应用程序委托和单例对象中。我对继承有点不确定。这两个方法本身是否在继承的对象中?也许如果我可以问,我真的很感激一些伪代码来帮助我在这里绘制一张放置图片。谢谢。这可能是一个真正的帮助。
  • 并非如此。据我了解,您在过度释放 NSString 对象时遇到问题,因此您需要为 NSString 对象创建一个子对象,并在代码中创建不是 NSString 而是您自己的字符串,然后遵循她的生命周期。
  • 这些覆盖了 NSObject 中的保留/释放函数,允许您在调用它们时设置断点。这个方法我也用过。
  • @progrmr 你说得对 NSObject 是对的,但如果它是所有事物的根对象,那么捕获一个实际上可能每个应用程序只有一个实例的特定对象可能太多了。 :) 但是是的,看来你和我达到了同样的禅意。
  • @ric:我扩展了这个答案以展示你如何将这两种方法放入一个类中,我称之为 DebugString。现在,无论您认为哪个 NSString 有问题,都将其声明从 NSString* 更改为 DebugString* 。它的工作原理完全相同,除了所有保留和释放也将通过这两种方法,您可以在它们上设置断点并查看调用堆栈以查看是谁调用了它。希望这可以帮助。 Nikita 希望你不介意我编辑了你的答案。
【解决方案2】:

在模拟器中运行时手动调用位置“didUpdate” - 在您启动位置管理器后,至少两次调用超时约五秒。这应该会触发与手机相同的错误,然后您可以使用 NSZombies。

此外,模拟器应该能够运行位置代码,我认为这在 4.2 中已损坏,但在 4.1 中可以。

【讨论】:

    猜你喜欢
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-23
    • 2014-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多