XCode 内置GDB,咱们能够在命令行中使用 GDB 命令来调试咱们的程序。下面将介绍一些经常使用的命令以及调试技巧。app
po 命令:为 print object 的缩写,显示对象的文本描述(显示从对象的 description 消息得到的字符串信息)。iphone
好比:函数
上图中,我使用 po 命令显示一个 NSDictionary 的内容。注意在左侧咱们能够看到 dict 的一些信息:3 key/value pairs,显示该 dict 包含的数据量,而展开的信息显示 isa 层次体系(即class 和 metaclass结构关系)。咱们能够右击左侧的 dict,选中“Print Description of "dict"”,则能够在控制台输出 dict 的详细信息:工具
[cpp] view plaincopyprint?ui
Printing description of dict: spa
<CFBasicHash 0x1001149e0 [0x7fff7e27ff40]>{type = immutable dict, count = 3, 命令行
entries => debug
0 : <CFString 0x100002458 [0x7fff7e27ff40]>{contents = "first"} = <CFString 0x100002438 [0x7fff7e27ff40]>{contents = "one"} 3d
1 : <CFString 0x100002498 [0x7fff7e27ff40]>{contents = "second"} = <CFString 0x100002478 [0x7fff7e27ff40]>{contents = "two"} 调试
2 : <CFString 0x1000024d8 [0x7fff7e27ff40]>{contents = "third"} = <CFString 0x1000024b8 [0x7fff7e27ff40]>{contents = "three"}
}
(gdb)
print 命令:有点相似于格式化输出,能够输出对象的不一样信息:
如:
[cpp] view plaincopyprint?
(gdb) print (char *)[[dict description] cStringUsingEncoding:4]
$1 = 0x1001159c0 "{\n first = one;\n second = two;\n third = three;\n}"
(gdb) print (int)[dict retainCount]
$2 = 1
(gdb)
注:4是 NSUTF8StringEncoding 的值。
info 命令:咱们能够查看内存地址所在信息
好比 "info symbol 内存地址" 能够获取内存地址所在的 symbol 相关信息:
[cpp] view plaincopyprint?
(gdb) info symbol 0x00000001000017f7
main + 343 in section LC_SEGMENT.__TEXT.__text of /Users/LuoZhaohui/Library/Developer/Xcode/DerivedData/RunTimeSystem-anzdlhiwvlbizpfureuvenvmatnp/Build/Products/Debug/RunTimeSystem
好比 "info line *内存地址" 能够获取内存地址所在的代码行相关信息:
[cpp] view plaincopyprint?
(gdb) info line *0x00000001000017f7
Line 62 of "/Users/LuoZhaohui/Documents/Study/RunTimeSystem/RunTimeSystem/main.m" starts at address 0x1000017f7 <main+343> and ends at 0x10000180a <main+362>.
show 命令:显示 GDB 相关的信息。如:show version 显示GDB版本信息
[cpp] view plaincopyprint?
(gdb) show version
GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Mon Aug 8 20:32:45 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".
help 命令:若是忘记某条命令的语法了,可使用 help 命令名 来获取帮助信息。如:help info 显示 info 命令的用法。
[cpp] view plaincopyprint?
(gdb) help info
Generic command for showing things about the program being debugged.
List of info subcommands:
info address -- Describe where symbol SYM is stored
info all-registers -- List of all registers and their contents
info args -- Argument variables of current stack frame
info auxv -- Display the inferior's auxiliary vector
info breakpoints -- Status of user-settable breakpoints
info catch -- Exceptions that can be caught in the current stack frame
info checkpoints -- Help
info classes -- All Objective-C classes
......
Type "help info" followed by info subcommand name for full documentation.
Command name abbreviations are allowed if unambiguous.
(gdb)
在系统抛出异常处设置断点
有时候咱们的程序不知道跑到哪一个地方就 crash 了,而 crash 又很难重现。保守的作法是在系统抛出异常以前设置断点,具体来讲是在 objc_exception_throw处设置断点。设置步骤为:首先在 XCode 按 CMD + 6,进入断点管理窗口;而后点击右下方的 +,增长新的 Symbolic Breakpoint,在 Symbol 一栏输入:objc_exception_throw,而后点击 done,完成。 这样在 Debug 模式下,若是程序即将抛出异常,就能在抛出异常处中断了。好比在前面的代码中,我让 [firstObjctcrashTest]; 抛出异常。在 objc_exception_throw 处设置断点以后,程序就能在该代码处中断了,咱们从而知道代码在什么地方出问题了。
一、使用僵尸变量(NSZombieEnabled)
二、重写object的respondsToSelector方法
在iphone开发的时候EXC_BAD_ACCESS这个bug时不容易找到缘由的。
首先说一下EXC_BAD_ACCESS 这个错误,能够这么说,90%的错误来源在于对一个已经释放的对象进行release操做,或者操做一个在循环代码中被修改的序列中的对象。虽然使用NSZombieEnabled变量能够帮助你找到问题所在,但有的时候,即便经过设置NSZombieEnabled变量,仍是不能定位到问题所在,这个时候,你能够试试重写object的respondsToSelector方法,显示出现EXEC_BAD_ACCESS前访问的最后一个object,下面是具体的步骤:
a、在每一个类而且在 other c flags中加入-D _FOR_DEBUG_(记住请只在Debug Configuration下加入此标记)。这样当你程序崩溃时,Xcode的console上就会准确地记录了最后运行的object的方法。的实现文件(.m,.mm)文件中,添加以下代码:
[cpp]
-(BOOL) respondsToSelector : (SEL)aSelector {
printf("SELECTOR: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:aSelector];
}
b、而且在 other c flags中加入-D _FOR_DEBUG_(记住请只在Debug Configuration下加入此标记)。这样当你程序崩溃时,Xcode的console上就会准确地记录了最后运行的object的方法。
三、让XCode反馈足够多的信息
在Edit–>Scheme里面 找到Arguments ,在Environment Variables这里添加
把下面2个值设置成YES
NSAutoreleaseFreedObjectCheckEnabled
NSDebugEnabled
这种方法很是好用,建议在创建一个工程的时候,加入此设置
四、设置全局异常断点
在程序抛出异常时候,每每须要定位到异常
键入快捷键 cmd + 6 进入断点窗口,点击左下角的"+"按钮,选择弹出框的“Add Exception BreakPoint”项,以下图所示:
而后使用默认设置,点击"done"按钮,设置全局异常断点就完成了