******
调试宏:
NSLog(@"%s,%d,%s,",__FILE__,__LINE__,__FUNCTION__);
1) __VA_ARGS__是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错, 你可以试试。
2) __FILE__ 宏在预编译时会替换成当前的源文件名
3) __LINE__宏在预编译时会替换成当前的行号
4) __FUNCTION__宏在预编译时会替换成当前的函数名称
********
Xcode 一般会在 debug 运行配置项里面已经定义号了DEBUG 标志,如果没定义我们就自己写上,以我的 Xcode 4 为例,在项目get Info中找到 PreProcessor Macros 这个属性,对于 Debug 配置我们给他写上 DEBUG,而在 Release 配置中把它留空。 这样我们刚才那段预处理命令就可以根据这个标志来判断我们编译的时调试版本还是发布版本,从而控制 NSLog 的输出。 (因为 Xcode 4 会把 debug/release 两个配置项同时对比展现出来,而 3.x 版本的只能分别设置,如果你用的时xcode 3.x 开发工具, 那么就分别对 Debug/Release 都检查一下)。在开发中可直接使用:
#ifdef DEBUG
#else
#define NSLog(format, ...)
#endif
*******
************************************** 附上一篇大牛的blog **************************************
XCode的一些调试技巧
罗朝辉 (http://blog.csdn.net/kesalin/)
CC 许可,转载请注明出处
XCode 内置GDB,我们可以在命令行中使用GDB 命令来调试我们的程序。下面将介绍一些常用的命令以及调试技巧。
po 命令:为 print object 的缩写,显示对象的文本描述(显示从对象的 description 消息获得的字符串信息)。
比如:
上图中,我使用 po 命令显示一个 NSDictionary 的内容。注意在左侧我们可以看到 dict 的一些信息:3 key/value pairs,显示该 dict 包含的数据量,而展开的信息显示 isa 层次体系(即class 和 metaclass结构关系)。我们可以右击左侧的 dict,选中“Print Description of "dict"”,则可以在控制台输出 dict 的详细信息:
- Printingdescriptionofdict:
- <CFBasicHash0x1001149e0[0x7fff7e27ff40]>{type=immutabledict,count=3,
- entries=>
- 0:<CFString0x100002458[0x7fff7e27ff40]>{contents="first"}=<CFString0x100002438[0x7fff7e27ff40]>{contents="one"}
- 1:<CFString0x100002498[0x7fff7e27ff40]>{contents="second"}=<CFString0x100002478[0x7fff7e27ff40]>{contents="two"}
- 2:<CFString0x1000024d8[0x7fff7e27ff40]>{contents="third"}=<CFString0x1000024b8[0x7fff7e27ff40]>{contents="three"}
- }
- (gdb)
print 命令 :有点类似于格式化输出,可以输出对象的不同信息:
如:
- (gdb)print(char*)[[dictdescription]cStringUsingEncoding:4]
- $1=0x1001159c0"{\nfirst=one;\nsecond=two;\nthird=three;\n}"
- (gdb)print(int)[dictretainCount]
- $2=1
- (gdb)
注:4是 NSUTF8StringEncoding 的值。
info 命令:我们可以查看内存地址所在信息
比如 "info symbol 内存地址" 可以获取内存地址所在的 symbol 相关信息:
- (gdb)infosymbol0x00000001000017f7
- main+343insectionLC_SEGMENT.__TEXT.__textof/Users/LuoZhaohui/Library/Developer/Xcode/DerivedData/RunTimeSystem-anzdlhiwvlbizpfureuvenvmatnp/Build/Products/Debug/RunTimeSystem
比如 " info line *内存地址 " 可以获取内存地址所在的代码行相关信息:
- (gdb)infoline*0x00000001000017f7
- Line62of"/Users/LuoZhaohui/Documents/Study/RunTimeSystem/RunTimeSystem/main.m"startsataddress0x1000017f7<main+343>andendsat0x10000180a<main+362>.
show 命令:显示 GDB 相关的信息。如:show version 显示GDB版本信息
- (gdb)showversion
- GNUgdb6.3.50-20050815(Appleversiongdb-1708)(MonAug820:32:45UTC2011)
- Copyright2004FreeSoftwareFoundation,Inc.
- GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouare
- welcometochangeitand/ordistributecopiesofitundercertainconditions.
- Type"showcopying"toseetheconditions.
- ThereisabsolutelynowarrantyforGDB.Type"showwarranty"fordetails.
- ThisGDBwasconfiguredas"x86_64-apple-darwin".
help 命令:如果忘记某条命令的语法了,可以使用 help 命令名 来获取帮助信息。如:help info 显示 info 命令的用法。
- (gdb)helpinfo
- Genericcommandforshowingthingsabouttheprogrambeingdebugged.
- Listofinfosubcommands:
- infoaddress--DescribewheresymbolSYMisstored
- infoall-registers--Listofallregistersandtheircontents
- infoargs--Argumentvariablesofcurrentstackframe
- infoauxv--Displaytheinferior'sauxiliaryvector
- infobreakpoints--Statusofuser-settablebreakpoints
- infocatch--Exceptionsthatcanbecaughtinthecurrentstackframe
- infocheckpoints--Help
- infoclasses--AllObjective-Cclasses
- ......
- Type"helpinfo"followedbyinfosubcommandnameforfulldocumentation.
- Commandnameabbreviationsareallowedifunambiguous.
- (gdb)
在系统抛出异常处设置断点
有时候我们的程序不知道跑到哪个地方就 crash 了,而 crash 又很难重现。保守的做法是在系统抛出异常之前设置断点,具体来说是在objc_exception_throw处设置断点。设置步骤为:首先在 XCode 按 CMD + 6,进入断点管理窗口;然后点击右下方的 +,增加新的 Symbolic Breakpoint,在 Symbol 一栏输入:objc_exception_throw,然后点击 done,完成。这样在 Debug 模式下,如果程序即将抛出异常,就能在抛出异常处中断了。比如在前面的代码中,我让[firstObjctcrashTest]; 抛出异常。在 objc_exception_throw 处设置断点之后,程序就能在该代码处中断了,我们从而知道代码在什么地方出问题了。
ref:http://blog.csdn.net/kesalin/article/details/7222153