Iphone 如何判断何时发送对象释放消息?

Iphone 如何判断何时发送对象释放消息?,iphone,objective-c,cocoa-touch,Iphone,Objective C,Cocoa Touch,我正在处理一个有点棘手的iPhone崩溃,看起来罪魁祸首是一个NSString被过早释放。我打开了NSZombiesEnabled,可以看到NSString在崩溃时是一个僵尸。但是,我无法确定对象何时被释放/解除分配——我已经仔细检查了我的代码,寻找发送到此对象的释放消息,并在这些位置设置了断点,但它们没有被命中 我假设这可能是一个线程或自动释放问题,因为它是间歇性的,但是有没有办法通过Xcode调试器连接到objective-c运行时来告诉对象被释放的确切位置?或者有更好的方法来诊断这个问题吗

我正在处理一个有点棘手的iPhone崩溃,看起来罪魁祸首是一个NSString被过早释放。我打开了NSZombiesEnabled,可以看到NSString在崩溃时是一个僵尸。但是,我无法确定对象何时被释放/解除分配——我已经仔细检查了我的代码,寻找发送到此对象的释放消息,并在这些位置设置了断点,但它们没有被命中


我假设这可能是一个线程或自动释放问题,因为它是间歇性的,但是有没有办法通过Xcode调试器连接到objective-c运行时来告诉对象被释放的确切位置?或者有更好的方法来诊断这个问题吗?

我可能没有想清楚,但是您是否考虑过在类中添加一个发布和解除锁定

- (void) release 
{
  NSLog(@"Releasing");
  [super release];
}
- (void) dealloc
{
  NSLog(@"Deallocating");
  [super dealloc];
}
结合Ben Gotow的评论使用obj-c类别,您将得到以下结果:

@interface NSString (release) 
  -(void) release;
@end

@implementation NSString (release)
-(void) release
{
  NSLog(@"NSString Released!");
  [super release];
}
@end

我的想法可能不太清楚,但您是否考虑过在类中添加一个release和dealloc

- (void) release 
{
  NSLog(@"Releasing");
  [super release];
}
- (void) dealloc
{
  NSLog(@"Deallocating");
  [super dealloc];
}
结合Ben Gotow的评论使用obj-c类别,您将得到以下结果:

@interface NSString (release) 
  -(void) release;
@end

@implementation NSString (release)
-(void) release
{
  NSLog(@"NSString Released!");
  [super release];
}
@end

能否实现dealloc()并在其中设置断点?从该点查看堆栈跟踪应该可以告诉您它在哪里以及如何被释放。

能否实现dealloc()并在其中设置断点?从该点查看堆栈跟踪应该可以告诉您它被释放的位置和方式。

您可以告诉
dtrace
objc
提供者在调用
-[NSString release]
时触发您的探测,但这将涉及到一些恶意黑客行为。NSStrings实际上不是NSStrings,而是所有的子类,因为类是作为类集群实现的。现在,这不会妨碍我们;什么是
NSString
没有自己的
-release
:-)。不过,您可以在类别中提供自己的


或者,如果您很容易判断
NSString
的哪个实例将要中断,您可以使用
self==myInstance
dtrace
objc
提供程序上设置一个条件断点,以便在
dtrace
的任何时候触发您的探测-[字符串释放]调用了,但这会涉及到一些令人讨厌的黑客行为。NSStrings实际上不是NSStrings,而是所有的子类,因为类是以类集群的方式实现的。现在,这不会妨碍我们的工作;
NSStrings
没有自己的
-release
:-)。您可以在c中提供自己的不过,是分类法


或者,如果您很容易判断
NSString
的哪个实例将要崩溃,您可以使用
self==myInstance

-[NSObject dealloc]
上设置一个条件断点。如果您可以在模拟器中重现崩溃,您可能希望使用
malloc\u history
工具。(它有一个手册页。)您需要设置一些环境变量:我通常通过“编辑活动可执行文件”来设置它们屏幕中的参数窗格,然后使用其中的复选框启用/禁用它们。确保在设备上调试之前禁用它们;如果启用,程序将尝试写入沙盒不允许的
/tmp

我发现此工具与
NSZombie
结合使用,可以跟踪解除锁定错误后的alloc/过早释放/访问。一旦
NSZombie
报告对解除锁定对象的访问,您可以使用
malloc\u history
计算对象的分配时间。这通常会让我找到问题所在的路径

我发现的另一个非常有价值的工具是LLVM项目中的clang。它仍在开发中,但它们定期为MacOS-X生成二进制文件,在我看来非常稳定。特别是,它了解Cocoa内存管理策略。使用它非常简单:

% cd ${DIRECTORY_CONTAINING_XCODE_PROJECT}
% xcodebuild clean
% scan-build -V xcodebuild

这将对您的项目进行完整构建,并生成一份报告,列出工具发现的任何明显错误(包括引用计数错误)。

如果您可以在模拟器中再现崩溃,您可能希望使用
malloc_history
工具进行研究。(它有一个手册页。)您需要设置一些环境变量:我通常通过参数窗格中的“编辑活动可执行文件”屏幕进行设置,然后使用那里的复选框启用/禁用它们。确保在设备上调试之前禁用它们;如果启用,程序将尝试写入沙箱不允许的
/tmp

我发现此工具与
NSZombie
结合使用,可以跟踪解除锁定错误后的alloc/过早释放/访问。一旦
NSZombie
报告对解除锁定对象的访问,您可以使用
malloc\u history
计算对象的分配时间。这通常会让我找到问题所在的路径

我发现的另一个非常有价值的工具是LLVM项目中的clang。它仍在开发中,但它们定期为MacOS-X生成二进制文件,在我看来非常稳定。特别是,它了解Cocoa内存管理策略。使用它非常简单:

% cd ${DIRECTORY_CONTAINING_XCODE_PROJECT}
% xcodebuild clean
% scan-build -V xcodebuild

这将完成项目的完整构建,并生成一份报告,列出任何明显的错误(包括引用计数错误)工具找到的。

另一种方法。确保打开NSZombie,使其报告获得额外版本的对象的内存地址。然后使用性能工具->对象分配运行。这将打开工具。查看Xcode organizer提供的控制台日志。一旦获得崩溃,请查找内存地址ess在instruments中。您将在该对象上看到mallocs/frees的整个历史,以及直接链接到代码中的链接。

另一种方法。请确保将NSZombie