使用xcode调试僵尸对象

在写obj-c代码的时候,僵尸对象是比较麻烦的问题.僵尸对象是指,提前释放内存的对象.对于iphone/mac程序来说,出现这个问题的原因一般有 2个,第一,程序员自己过早释放内存,第二,使用了外部框架导致的.第一点很容易查出来,第二点来说,主要是因为外部框架一般会使用 autorelease,如果对框架怎么运行不清楚的话,提前手动释放内存,就会使自动释放内存的时候出错.
举例来说:
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSData* data = [NSData dataWithBytes:"asklaskdxjgr" length:12];
[data release];
[pool release];
由于NSData的dataWithBytes是类方法,并且会设置autorelease,所以在pool释放内存的时候,data已经是僵尸对象.

解决方法来说一般也是2个,第一个所有对象都使用autorelease方式,但是这种方式的问题在于performance不怎么好,而且也不利于程序员水平的提高.第二个就是找到僵尸对象,查看其调用关系,理顺内存释放顺序.那么找到僵尸对象就成为了急需解决的问题.

苹果有个头文件,叫NSDebug.h,具体在
这里 . 很久以前就是靠引入这个头文件来解决问题.当然随着obj-c 2.0的引入,我们可以不再用这么古老的方式.新的做法如下:

1 在xode里右击可执行文件,选择get info-->arguments-->Variables to be set in the ENV

2 添加以下变量
NSDebugEnabled
NSZombieEnabled
MallocStackLogging
MallocStackLoggingNoCompact
?设置他们的值为YES.

3 在debug模式下运行程序,到pool release的时候,会在console上看到:
2010-12-25 08:01:38.644 autoreleasebug[3939] *** *** Selector 'release'
sent to dealloced instance 0xa4e10 of class NSConcreteData.
这就说明有僵尸对象出现,给了进程id--3939,对象内存地址--0xa4e10.

4 接下来在console里敲shell malloc_history pid(3939) address(0xa4e10).得到调用关系如下:

Call [2] [arg=24]: thread_a000a1ec |0x0 | _dyld_start | _start | main | NSApplicationMain
| -[NSApplication run] | -[NSApplication sendEvent:] | -[NSWindow sendEvent:]
| -[NSControl mouseDown:] | -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:]
| -[NSCell trackMouse:inRect:ofView:untilMouseUp:] | -[NSCell _sendActionFrom:]
| -[NSControl sendAction:to:] | -[NSApplication sendAction:to:from:] | -[MEController 
newCity:] | -[MECityEditor editCity:otherCities:] | -[NSApplicationrunModalForWindow:]
| -[NSApplication _realDoModalLoop:peek:] | -[NSApplication nextEventMatchingMask:
untilDate:inMode:dequeue:] | _DPSNextEvent | BlockUntilNextEventMatchingListInMode
| ReceiveNextEventCommon | RunCurrentEventLoopInMode | CFRunLoopRunSpecific
| __CFRunLoopRun | __CFRunLoopDoObservers | _handleWindowNeedsDisplay | -[NSWindow 
displayIfNeeded] | -[NSView displayIfNeeded] | -[NSView _displayRectIgnoringOpacity:
isVisibleRect:rectIsVisibleRectForView:] | -[NSThemeFrame 
_recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:
topView:] | -[NSFrameView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:
rectIsVisibleRectForView:topView:] | -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:
isVisibleRect:rectIsVisibleRectForView:topView:] | -[NSView
_recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
| -[NSView(NSInternal) _getDirtyRects:clippedToRect:count:boundingBox:] | -[NSRegion 
mutableCopy] | NSAllocateObject | _internal_class_createInstanceFromZone | malloc_zone_ca
lloc

根据这个调用关系,我们就可以哪个对象被提前释放了,从而修改程序.


http://blog.sina.com.cn/s/blog_57e160a30100nihf.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值