OC中如何调试野指针异常(EXC_BAD_ACCESS(code = ....))
来源:互联网 发布:输入字符串统计java 编辑:程序博客网 时间:2024/06/14 02:51
一哥们儿(__weak_Point)把自己在百度的面试题贴到了网上 面试题在百度面试题第八题 ,刚好当初公司面试我的时候也问到了这个问题。(当时没回答上来,最近又看到这个问题,就问总结了一下)
相信很多的人在工作和学习中都会遇到这个问题
图中的代码如下,注意代码是再非ARC中运行的
//注意,这些代码是在非ARC下运行的。 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. UIView * view1 = [[UIView alloc]init]; //View1指向对象的引用计数为0,对象销毁4 [self freeView:view1]; //view的对象此时已销毁,出现野指针,程序崩溃 [view1 setBackgroundColor:[UIColor orangeColor]];}//将传过来的对象release掉- (void)freeView:(NSObject *)obj{ [obj release];}
上面的代码很简单,一眼就可以看出什么地方出了问题,但是在实际的工作中,代码逻辑关系都很复杂,如果不小心释放了对象,出现这个问题,找起来是比较麻烦的。尤其是接管别人的代码。
这里就来说一下具体的结局方案
我们知道程序运行的时候,我们创建的对象都是存储在堆内存上的。我们可以通过监测堆内存上内存的变化,来监出现野指针的区域。这样就可以知道在哪里出现了问题。
Xcode 提供了运行程序时记录当前进程 堆内存变化的功能。现在我们打开这个功能,如下图所示。
然后我们运行程序,注意控制台输出。
malocHistory(3491,0x10d8ae300) malloc: stack logs being written into /tmp/stack-logs.3491.114ce0000.malocHistory.TJzvuk.indexmalocHistory(3491,0x10d8ae300) malloc: recording malloc and VM allocation stacks to disk using standard recordermalocHistory(3491,0x10d8ae300) malloc: process 3308 no longer exists, stack logs deleted from /tmp/stack-logs.3308.1126eb000.malocHistory.Kovf7r.index
控制台中说大概意思就是内存非配得历史已经开始记录,被写在了/tmp/stack-logs 文件夹下面。某个进程(process)已经不再存在了。记录他的mallocHistoy文件被删除。
我们到这个目录上看一下。(下面的代码是在我的pro上控制台中输入的,截图太慢了,==\\)
zhangxuongdeMBP:tmp zhangxudong$ cd /tmpzhangxuongdeMBP:tmp zhangxudong$ lsKSOutOfProcessFetcher.501.IW-ShwaXJwmHlkfc5wb2ZMHOaJY=NanoPreferencesSyncPlugInKit-Annotationscom.apple.CoreSimulator.SimDevice.6CAB348C-8E57-4F2A-A2B3-3326F2F84D8D.launchd_simcom.apple.CoreSimulator.SimDevice.D83EE71A-C375-44A4-8F5F-E704CAED94FE.launchd_simcom.apple.launchd.0u21btl7qCcom.apple.launchd.Vl0gfUy0kTcom.apple.launchd.YgEnK6wsOicom.apple.launchd.kXJa1h1Vr9com.apple.launchd.v3PwxXkHWXcom.sogou.inputmethodfm_sg_cloud_cache.v0.filemap.sogouime_3.2.0.69954_00000000_501stack-logs.3491.114ce0000.malocHistory.TJzvuk.index #这个就是控制台中讲的文件zhangxuongdeMBP:tmp zhangxudong$
我们查看一下 这个文件
zhangxuongdeMBP:tmp zhangxudong$ cat stack-logs.3491.114ce0000.malocHistory.TJzvuk.index U5??%?pU??ƚ?pU???0?U5?s?UU???k?UU???x?U???FbE?U????BT?????U??? ?5U????C@uU????a%U???K?U????(?U????u(?U????u(UT????u(W????u(?W????uUUл???(UUл??u(eUл??u(5Uл??u(?Uл??u(?Uл??u(?Uл??u(uTл??u(Tл??u(?Tл??u(?Tл??u(?Tл??u(EWл??u(Wл??u(%Wл??u(?Wл??u(?Wл??u(UVл??u(eVл??u(5Vл??u(?Vл??u(?Vл??u(?Vл??u(uQл??u(Qл??u(?Qл??u(?Qл??u(?Qл??u(EPл??u(Pл??u(%Pл??u(?Pл??u(?Pл??u(USл??u(eSл??u(5Sл??u(?Sл??u(?Sл??u?Sл?? ERл?c eRл?MRл?ď 5Rл?ü?Rл?? ?Rл??0?Rл?Y_?Rл????Rл? Rл?é??Rл?z2Rл?VN ?Rл?&EÅл??uöл??,EÅл?R??Rл??U%???U???o?U%?6? EÅл? eÅл????UU???????UU????? Åл? ??Uu???Z?%Åл??% ?Åл???Åл?k% ?Åл??0?Åл?i??Åл?0?Rл??(?Åл?ÄU????(?Åл??;U???0?UU??ɻ?UU??>Huöл??US??>HUU???DUE??>HUS???D Uw??>HUE???D@U??>HUw???D?U???>HU???DUÅ??>HU????DU???6?U??>HÅ???DU???6?U??>HU???U???6U??>HU???DU???6?U??>HU???D?Åл?huöл?oXeÜл??)?Üл??X?^л??)EYл??XeYл??)?Yл??X?Yл??)EXл??XeXл??)?Xл??X?Xл??)E[л??Xe[л??)?[л??X?[л??)EZл??XeZл??)!?Zл??X?Zл??)uEл??XEл??)?Eл??X?Eл??)uDл??XDл??)Rл??X?Dл??)UGл??XuGл??)?Gл??X?Gл??)//........此处省略一万行 反正也看不懂.......................?ӻ?>j?ӻ???ߐ????U}???F5?????D???????????.??I???~??K?????zhangxuongdeMBP:tmp zhangxudong$
恩,这个文件我们是读不懂了。下面使用malloc_history 命令
查看一下命令帮助
zhangxuongdeMBP:images zhangxudong$ malloc_history --help[invalid usage]: no process id or name specified //无效的使用方法,没有制定有效的进程id或者进程名malloc_history: Displays/aggregates allocation histories in a processUsage: malloc_history <pid/partial-process-name> [options] <mode> [<address> ...] //显示进程中内存分配的历史 使用方法是 malloc_history <进程id/或者进程的名字> [操作选项] <mode> [内存地址]'mode' should be one of {-callTree, -allBySize, -allByCount, -allEvents, or one or more addresses} -allBySize [mode] -allByCount [mode] -allEvents [mode] -callTree [mode] -highWaterMark -showContent (-calltree only) -invert (-calltree only) -ignoreThreads (-calltree only) -collapseRecursion (-calltree only) -chargeSystemLibraries (-calltree only) -consolidateAllBySymbol (-calltree only) -consolidateSystemFramesBySymbol (-calltree only)zhangxuongdeMBP:images zhangxudong$
进程名,可以通过上面控制台的输出知道,3491。
对应的内存地址,从前前面已经知道是 0x00007fcbbd9345f0
从控制台中查询。
zhangxuongdeMBP:images zhangxudong$ malloc_history 3491 0x00007fcbbd9345f0malloc_history Report Version: 2.0Invalid connection: com.apple.coresymbolicationdALLOC 0x7fcbbd9345f0-0x7fcbbd93471f [size=304]: thread_10d8ae300 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoBlocks | __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ | __31-[FBSSerialQueue performAsync:]_block_invoke_2 | -[UIApplication workspaceDidEndTransaction:] | -[UIApplication _runWithMainScene:transitionContext:completion:] | -[UIApplication _createStatusBarWithRequestedStyle:orientation:hidden:] | -[UIWindow _initWithOrientation:] | -[UIView init] | -[UIStatusBarWindow initWithFrame:] | -[UIWindow _initWithFrame:debugName:scene:attached:] | -[UIApplication _updateCurrentStatusBarViewControllerAppearance] | -[UIApplication _setStatusBarStyle:animationParameters:] | -[UIStatusBar _requestStyleAttributes:animationParameters:] | -[UIStatusBar _prepareToSetStyle:animation:] | +[UIView(Animation) performWithoutAnimation:] | __44-[UIStatusBar _prepareToSetStyle:animation:]_block_invoke | -[UIStatusBarForegroundView setStatusBarData:actions:animated:] | -[UIStatusBarForegroundView _setStatusBarData:actions:animated:] | -[UIStatusBarForegroundView _reflowItemViewsWithDuration:preserveHistory:] | -[UIStatusBarForegroundView _computeVisibleItemsPreservingHistory:] | -[UIStatusBarLayoutManager distributeOverlap:amongItems:] | -[UIStatusBarServiceItemView addContentOverlap:] | -[UIStatusBarServiceItemView updateContentsAndWidth] | -[UIStatusBarServiceItemView _contentsImageFromString:withWidth:letterSpacing:] | -[UIStatusBarForegroundStyleAttributes imageWithText:ofItemType:forWidth:lineBreakMode:letterSpacing:textAlignment:style:withLegibilityStyle:legibilityStrength:] | -[NSString(UIStringDrawingLegacy) _legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:] | -[NSString(NSExtendedStringDrawing) boundingRectWithSize:options:attributes:context:] | __NSStringDrawingEngine | CTLineCreateTruncatedLineWithTokenHandler | TTruncator::EndTruncate(double, __CTRun const* (__CTLine const*, CFRange*, __CFDictionary const*) block_pointer) | TTruncator::CreateToken(CFRange&, __CTRun const* (__CTLine const*, CFRange*, __CFDictionary const*) block_pointer) | ____NSStringDrawingEngine_block_invoke_2 | CTLineCreateWithAttributedString | TTypesetterAttrString::TTypesetterAttrString(__CFAttributedString const*) | TTypesetterAttrString::Initialize(__CFAttributedString const*) | TGlyphEncoder::EncodeChars(CFRange, TAttributes const&, TGlyphList<TDeletedGlyphIndex>&, TGlyphEncoder::Fallbacks) | _CFRuntimeCreateInstance | malloc_zone_malloc ----FREE 0x7fcbbd9345f0-0x7fcbbd93471f [size=304]: thread_10d8ae300 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoBlocks | __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ | __31-[FBSSerialQueue performAsync:]_block_invoke_2 | -[UIApplication workspaceDidEndTransaction:] | -[UIApplication _runWithMainScene:transitionContext:completion:] | -[UIApplication _createStatusBarWithRequestedStyle:orientation:hidden:] | -[UIWindow _initWithOrientation:] | -[UIView init] | -[UIStatusBarWindow initWithFrame:] | -[UIWindow _initWithFrame:debugName:scene:attached:] | -[UIApplication _updateCurrentStatusBarViewControllerAppearance] | -[UIApplication _setStatusBarStyle:animationParameters:] | -[UIStatusBar _requestStyleAttributes:animationParameters:] | -[UIStatusBar _prepareToSetStyle:animation:] | +[UIView(Animation) performWithoutAnimation:] | __44-[UIStatusBar _prepareToSetStyle:animation:]_block_invoke | -[UIStatusBarForegroundView setStatusBarData:actions:animated:] | -[UIStatusBarForegroundView _setStatusBarData:actions:animated:] | -[UIStatusBarForegroundView _reflowItemViewsWithDuration:preserveHistory:] | -[UIStatusBarForegroundView _computeVisibleItemsPreservingHistory:] | -[UIStatusBarLayoutManager distributeOverlap:amongItems:] | -[UIStatusBarServiceItemView addContentOverlap:] | -[UIStatusBarServiceItemView updateContentsAndWidth] | -[UIStatusBarServiceItemView _contentsImageFromString:withWidth:letterSpacing:] | -[UIStatusBarForegroundStyleAttributes imageWithText:ofItemType:forWidth:lineBreakMode:letterSpacing:textAlignment:style:withLegibilityStyle:legibilityStrength:] | -[UIStatusBarForegroundStyleAttributes drawText:forWidth:lineBreakMode:letterSpacing:textAlignment:style:textSize:textHeight:] | -[NSString(UIStringDrawingLegacy) _legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:] | -[NSAttributedString(NSExtendedStringDrawing) drawWithRect:options:context:] | __NSStringDrawingEngine | CTLineCreateTruncatedLineWithTokenHandler | TTruncator::EndTruncate(double, __CTRun const* (__CTLine const*, CFRange*, __CFDictionary const*) block_pointer) | TTruncator::CreateToken(CFRange&, __CTRun const* (__CTLine const*, CFRange*, __CFDictionary const*) block_pointer) | ____NSStringDrawingEngine_block_invoke_2 | CFRelease | malloc_zone_free ALLOC 0x7fcbbd9345f0-0x7fcbbd934647 [size=88]: thread_10d8ae300 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoBlocks | __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ | __31-[FBSSerialQueue performAsync:]_block_invoke_2 | -[UIApplication workspaceDidEndTransaction:] | -[UIApplication _runWithMainScene:transitionContext:completion:] | -[UIApplication _createStatusBarWithRequestedStyle:orientation:hidden:] | -[UIWindow _initWithOrientation:] | -[UIView init] | -[UIStatusBarWindow initWithFrame:] | -[UIWindow _initWithFrame:debugName:scene:attached:] | -[UIApplication _updateCurrentStatusBarViewControllerAppearance] | -[UIApplication _setStatusBarStyle:animationParameters:] | -[UIStatusBar _requestStyleAttributes:animationParameters:] | -[UIStatusBar _prepareToSetStyle:animation:] | +[UIView(Animation) performWithoutAnimation:] | __44-[UIStatusBar _prepareToSetStyle:animation:]_block_invoke | -[UIStatusBarForegroundView setStatusBarData:actions:animated:] | -[UIStatusBarForegroundView _setStatusBarData:actions:animated:] | -[UIStatusBarForegroundView _reflowItemViewsWithDuration:preserveHistory:] | -[UIStatusBarForegroundView _computeVisibleItemsPreservingHistory:] | -[UIStatusBarLayoutManager distributeOverlap:amongItems:] | -[UIStatusBarServiceItemView addContentOverlap:] | -[UIStatusBarServiceItemView updateContentsAndWidth] | -[UIStatusBarServiceItemView _contentsImageFromString:withWidth:letterSpacing:] | -[UIStatusBarForegroundStyleAttributes imageWithText:ofItemType:forWidth:lineBreakMode:letterSpacing:textAlignment:style:withLegibilityStyle:legibilityStrength:] | -[UIStatusBarForegroundStyleAttributes drawText:forWidth:lineBreakMode:letterSpacing:textAlignment:style:textSize:textHeight:] | -[NSString(UIStringDrawingLegacy) _legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:] | -[NSAttributedString(NSExtendedStringDrawing) drawWithRect:options:context:] | __NSStringDrawingEngine | CTLineDraw | TRun::DrawGlyphs(CGContext*, CFRange) const | CGGStateSetFont | maybe_copy_text_state | malloc | malloc_zone_malloc ----FREE 0x7fcbbd9345f0-0x7fcbbd934647 [size=88]: thread_10d8ae300 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoBlocks | __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ | __31-[FBSSerialQueue performAsync:]_block_invoke_2 | -[UIApplication workspaceDidEndTransaction:] | -[UIApplication _runWithMainScene:transitionContext:completion:] | -[UIApplication _createStatusBarWithRequestedStyle:orientation:hidden:] | -[UIWindow _initWithOrientation:] | -[UIView init] | -[UIStatusBarWindow initWithFrame:] | -[UIWindow _initWithFrame:debugName:scene:attached:] | -[UIApplication _updateCurrentStatusBarViewControllerAppearance] | -[UIApplication _setStatusBarStyle:animationParameters:] | -[UIStatusBar _requestStyleAttributes:animationParameters:] | -[UIStatusBar _prepareToSetStyle:animation:] | +[UIView(Animation) performWithoutAnimation:] | __44-[UIStatusBar _prepareToSetStyle:animation:]_block_invoke | -[UIStatusBarForegroundView setStatusBarData:actions:animated:] | -[UIStatusBarForegroundView _setStatusBarData:actions:animated:] | -[UIStatusBarForegroundView _reflowItemViewsWithDuration:preserveHistory:] | -[UIStatusBarForegroundView _computeVisibleItemsPreservingHistory:] | -[UIStatusBarLayoutManager distributeOverlap:amongItems:] | -[UIStatusBarServiceItemView addContentOverlap:] | -[UIStatusBarServiceItemView updateContentsAndWidth] | -[UIStatusBarServiceItemView _contentsImageFromString:withWidth:letterSpacing:] | -[UIStatusBarForegroundStyleAttributes imageWithText:ofItemType:forWidth:lineBreakMode:letterSpacing:textAlignment:style:withLegibilityStyle:legibilityStrength:] | PopContext | CFRelease | context_finalize | CGGStackRelease | CGGStackReset | CGGStateRelease | free ALLOC 0x7fcbbd9345f0-0x7fcbbd9346e7 [size=248]: thread_10d8ae300 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoBlocks | __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ | __31-[FBSSerialQueue performAsync:]_block_invoke_2 | -[UIApplication workspaceDidEndTransaction:] | -[UIApplication _runWithMainScene:transitionContext:completion:] | -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] | -[UIWindow makeKeyAndVisible] | -[UIWindow _setHidden:forced:] | -[UIWindow addRootViewControllerViewIfPossible] | -[UIViewController view] | -[UIViewController loadViewIfRequired] | -[UIViewController loadView] | -[UIViewController _loadViewFromNibNamed:bundle:] | -[UINib instantiateWithOwner:options:] | -[UINib unarchiverForInstantiatingReturningError:] | -[UINibDecoder initForReadingWithData:error:] | -[UINibDecoder validateAndIndexData:error:] | -[UINibDecoder validateAndIndexObjects:length:] | calloc | malloc_zone_calloc ----FREE 0x7fcbbd9345f0-0x7fcbbd9346e7 [size=248]: thread_10d8ae300 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoBlocks | __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ | __31-[FBSSerialQueue performAsync:]_block_invoke_2 | -[UIApplication workspaceDidEndTransaction:] | -[UIApplication _runWithMainScene:transitionContext:completion:] | -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] | -[UIWindow makeKeyAndVisible] | -[UIWindow _setHidden:forced:] | -[UIWindow addRootViewControllerViewIfPossible] | -[UIViewController view] | -[UIViewController loadViewIfRequired] | -[UIViewController loadView] | -[UIViewController _loadViewFromNibNamed:bundle:] | objc_object::sidetable_release(bool) | -[UINib dealloc] | objc_object::sidetable_release(bool) | -[UINibStorage dealloc] | objc_object::sidetable_release(bool) | -[UINibDecoder dealloc] | free ALLOC 0x7fcbbd9345f0-0x7fcbbd9346ff [size=272]: thread_10d8ae300 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoBlocks | __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ | __31-[FBSSerialQueue performAsync:]_block_invoke_2 | -[UIApplication workspaceDidEndTransaction:] | -[UIApplication _runWithMainScene:transitionContext:completion:] | -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] | -[UIWindow makeKeyAndVisible] | -[UIWindow _setHidden:forced:] | -[UIWindow addRootViewControllerViewIfPossible] | -[UIViewController view] | -[UIViewController loadViewIfRequired] | -[ViewController viewDidLoad] | _objc_rootAlloc | class_createInstance | calloc | malloc_zone_calloc ----FREE 0x7fcbbd9345f0-0x7fcbbd9346ff [size=272]: thread_10d8ae300 |start | main | UIApplicationMain | -[UIApplication _run] | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoBlocks | __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ | __31-[FBSSerialQueue performAsync:]_block_invoke_2 | -[UIApplication workspaceDidEndTransaction:] | -[UIApplication _runWithMainScene:transitionContext:completion:] | -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] | -[UIWindow makeKeyAndVisible] | -[UIWindow _setHidden:forced:] | -[UIWindow addRootViewControllerViewIfPossible] | -[UIViewController view] | -[UIViewController loadViewIfRequired] | -[ViewController viewDidLoad] | -[ViewController freeView:] | -[UIView dealloc] | -[UIResponder dealloc] | object_dispose | free zhangxuongdeMBP:images zhangxudong$
从这些输出中我们可以知道,堆这个内存的使用情况,从哪个方法中使用。他们的使用历史。
代码确实比较多,alloc(开辟地址) 和 free(释放地址) 成对出现 ,内存已经被释放了。注意最后一个free 有一句话 -[ViewController freeView:] 调用了个方法。之后 -[UIView dealloc] 。
现在已经确定了,问题所在。
- OC中如何调试野指针异常(EXC_BAD_ACCESS(code = ....))
- EXC_BAD_ACCESS异常 调试过程
- iphone如何调试EXC_BAD_ACCESS
- 如何调试EXC_BAD_ACCESS
- iPhone 如何调试 EXC_BAD_ACCESS
- iphone如何调试EXC_BAD_ACCESS
- 如何调试EXC_BAD_ACCESS
- 调试中遇到EXC_BAD_ACCESS
- xcode 4.2 如何调试 EXC_BAD_ACCESS
- xcode 4.2 如何调试 EXC_BAD_ACCESS
- xcode 4.2 如何调试 EXC_BAD_ACCESS
- 什么是EXC_BAD_ACCESS以及如何调试
- xcode 4.2 如何调试 EXC_BAD_ACCESS
- ios开发笔记----exc_bad_access(code=1, address=0x789870)野指针错误,假死debug状态
- 【OC】thread 1:exc_bad_access(code=1,address=0x7fff7d72a7a0) 的一种解决方法
- Xcode 5中调试 EXC_BAD_ACCESS
- imagePlayerview exc_bad_access(code=EXC_I386_GPFLT)
- iOS 崩溃调试 exc_bad_access(code=1,address=0x10)
- UIWindow
- NSCoding
- Modal
- erlang进程监控的实现原理
- 模仿UIImageView
- OC中如何调试野指针异常(EXC_BAD_ACCESS(code = ....))
- 图片水印
- 图片裁剪
- 屏幕截图
- 黑马程序员——JAVASE-IO流(上)
- Markdown写文章血的教训,需谨记
- 51单片机学习笔记【四】——定时器和中断系统
- redhat 查询端口占用
- Apache Web Server -> httpd 的长连接配置