iOS内存错误EXC_BAD_ACCESS的解决方法

程序偶然性的崩溃一般原因是:调用了已经释放的内存空间,或者说重复释放了某个地址空间。定位这个地址通过编辑xcode的scheme,添加如下标记位,让系统把错误地址打印出来。
iOS内存错误EXC_BAD_ACCESS的解决方法_第1张图片
屏幕快照 2018-04-03 上午9.47.28.png

再次崩溃时会打印出如下

-[__NSSetI release]: message sent to deallocated instance 0x1d4291b70

如果崩溃是发生在当前调用栈,通过上面的做法,系统就会把崩溃原因定位到具体代码中。但是,如果崩溃不在当前调用栈,系统就仅仅只能把崩溃地址告诉我们,而没办法定位到具体代码,这样我们也没法去修改错误。这时就可以修改scheme,让xcode记录每个地址alloc的历史,这样我们就可以用命令把这个地址还原出来。如图:(跟设置NSZombieEnabled一样,添加MallocStackLoggingNoCompact,并且设置为YES)
message sent to deallocated instance后会有一个内存地址,如:0×6497860,我们需要查看该地址的malloc history.查看方法,在原来的gdb下,使用”info malloc_history 0×6497860“即可显示malloc记录。但是新版的Xcode 不再支持,怎么办呢,我们还有terminal,使用终端的malloc_history命令,如”malloc_history 32009 0×6497860“即可显示。其中的32009是该进程的pid,根据这个malloc记录,可以大致定位出错信息的代码位置。
Terminal中 输入

malloc_history 32009 0xc9313d0 |grep 0xc9313d0

会出现类似以下提示代码,根据提示就可以找出错误具体位置

ALLOC 0xfcdff50-0xfce00b7 [size=360]: thread_3bf2a28 |start | main | UIApplicationMain | GSEventRun   
| GSEventRunModal | CFRunLoopRunInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoObservers   
| __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ | _afterCACommitHandler | _applyBlockToCFArrayCopiedToStack   
| ___afterCACommitHandler_block_invoke | __38-[UITableView touchesEnded:withEvent:]_block_invoke |  
 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] | -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] | -[MessageListViewController tableView:didSelectRowAtIndexPath:] | _objc_rootAlloc | class_createInstance | calloc | malloc_zone_calloc   

你可能感兴趣的:(iOS内存错误EXC_BAD_ACCESS的解决方法)