Xcode lldb调试命令

http://blog.csdn.net/qq871531334/article/details/50564434

lldb调试命令

  • n/next:step over,等效于F6;
  • s/step:step into,等效于(fn+)F7;
  • finish:step out,等效于(fn+)F8;
  • c/continue:goto next breakpoint,等效于^⌘Y
  • expr/expression:Evaluate a C/ObjC/C++ expression(动态执行C/ObjC/C++表达式);
  • p/print/expr/expression:print as a C/C++ basic variable;
// 打印SYSTEM_VERSION(可能要加UIDevice*转换)
(lldb)p [[[UIDevicecurrentDevicesystemVersion] doubleValue]
  • po/expr -O/expression -O:Print as an Objective-C object;
// 打印屏幕bounds(可能要加UIScreen*转换)
(lldb)po NSStringFromCGRect([[UIScreen mainScreen] bounds]) 
// 打印状态栏frame(可能要加UIApplication*转换)
(lldb)po NSStringFromCGRect([UIApplication sharedApplication].statusBarFrame)
// 打印当前keyWindow的根视图(可能要加UIViewController*转换
(lldb)po [[[UIApplication sharedApplication] keyWindow] rootViewController]
  • call:调用。其实上述p/po后接表达式(expression)也有调用的功能,一般只在不需要显式输出,或是无返回值时使用call,用于动态调试插入调用代码。
    例如可以在viewDidLoad:里面设置断点,然后在程序中断的时候输入以下命令:
// 调用后,继续运行程序,view的背景色将变成红色
(lldb) call [self.view setBackgroundColor:[UIColor redColor]]
  • bt(backtrace),打印当前调用堆栈(crash堆栈),“bt all”可打印所有thread的堆栈(相当于command+6的Debug Session Navigation)。
  • image:可用于寻址,有多个组合命令,比较实用的一种用法是寻找栈地址对应的代码(行)位置。
    例如某个UITableView总共有2个section,当其引用的currentSection.index≥2时将会引起[UITableView rectForHeaderInSection:]调用异常,可使用expr动态改值制造crash场景模拟调试。
    此时crash时的控制台bt显示异常出现在应用层代码“0x00d055b8 - [FACategoryTableView FACategorySectionHeaderDidTouched:] + 744”处(其中0x00d055b8为当前栈(代码段)偏移量,744为栈帧偏移量——PC指针相对函数入口的偏移)。
    那么具体是FACategoryTableView.m文件哪一行代码调用引起的异常呢?此时通过“image lookup --address”后接bt的call stack中的代码段偏移地址(0x00d055b8)即可定位出异常调用的代码行位置。
  • x/memory read:dump指定地址的内存(Read from the memory of the process being debugged),后接起止地址或-c指定count加起始地址。可help mem read查看帮助:

Syntax

memory read <cmd-options> <address-expression> [<address-expression>]

Command Options Usage:

size指定内存块(block/chunk)的大小

    --size <byte-size> ):The size in bytes to use when displaying with the selected format.

count指定内存块(block/item)的个数,可配合起始地址使用。

    -c <count> ( --count <count> ):The number of total items to display.

format指定内容显示格式,格式符同print:c-char,s-string,d-decimal,x-hex。

    -f <format> ( --format <format> ):Specify a format to be used for display.

Command Samples:

(a)起止地址,以下基于起始地址偏移量指定截至地址。

(lldb)mem read 0x10b88f0c 0x10b88f0c+9

0x10b88f0c: 39 38 37 36 35 34 33 32 31                       987654321

(b)可在起始地址后使用-c指定需要dump的字节数,以上等效:

(lldb)mem read 0x10b88f0c -c 9

0x10b88f0c: 39 38 37 36 35 34 33 32 31                       987654321

(c)起始地址+内存块size+内存块count(dump hex format)

(lldb)memory read -s 1 -f x -c 9 0x10b88f0c

0x10b88f0c: 0x39 0x38 0x37 0x36 0x35 0x34 0x33 0x32

0x10b88f14: 0x31

说明:dump的memory chunk为1byte,以上总共dump了chunk size*chunk count=9byte。

(d)起始地址+内存块size+内存块count(dump char format)

(lldb)memory read -s 1 -f c -c 9 0x10b88f0c

0x10b88f0c: 987654321

(e)起始地址+内存块size+内存块count(dump string format)

(lldb)mem read 0x10b5cf2c -f s -c 1

0x10b88f0c: "987654321"

(f)起始地址+内存块size+内存块count(dump int format)

(lldb)memory read -s 4 -f x -c 3 0x10b88f0c

0x10b88f0c: 0x36373839 0x32333435 0x109f0031

说明:以上指定chunk尺寸为4byte(-s  4),chunk数量为3,共dump了12个byte。

  • memory write:改写指定地址的内存(Write to the memory of the process being debugged)。可自行help mem write查看帮助:

Syntax: memory write <cmd-options> <address> <value> [<value> [...]]

trick:lldb打印无效问题

在使用LLDB调试命令p/po打印C类型(包括复合类型)或Objective-C对象时,可能会遇到属性不存在或类型不匹配的问题。

例1——断点调试,打印当前UIViewController的frame:

  • 由于Xcode lldb本身的bug,对属性的点引用有时会无法识别,例如执行(lldb) p self.view.frame报错:property 'frame' not found on object of type 'UIView *'
  • 将对属性的点引用改为对属性的getter调用,执行(lldb) p [self.view frame]依旧报错:no known method '-frame'; cast the message send to the method's return type
  • 由于Xcode lldb本身的bug,对返回的复合类型也无法直接识别,此时可采用显示类型转换,执行(lldb) p (CGRect)[self.view frame]不会报错!

例2——断点调试,打印当前UIViewController的navigationController堆栈和childViewControllers数组

点引用报错写法(property not found):(lldb) po self.navigationController.viewControllers

调用getter正确打印:(lldb) po [[self navigationController] viewControllers]

点引用报错写法(property not found):(lldb) po self.childViewControllers

调用getter正确打印:(lldb) po [self childViewControllers]

(6)启用NSZombieEnabled调试EXC_BAD_ACCESS

当你对已释放的对象发送消息(90%的可能是对引用计数为0的对象再release)或release那些autorelease对象时,就会出现报EXC_BAD_ACCESS这样的错误。
默认设置下 Xcode不会给你定位具体是哪一行代码不该去使用已释放的对象,或者release用错了。
Product -> Edit Schemeoption+command+R -> Diagnostics ,勾选“Objective-C”之后的“Enable Zombie Objects”。
设置NSZombieEnabled环境变量后,一个对象销毁时会被转化为_NSZombie;设置NSZombieEnabled后,当你向一个已经释放的对象发送消息,这个对象就不只是报EXC_BAD_ACCESS Crash,还会放出一个错误消息,然后以一种可预测的可以产生debug断点的方式消失, 因此我们可以找到具体或者大概是哪个对象被错误的释放或引用了。
注意:NSZombieEnabled只能在调试的时候使用,千万不要忘记在产品发布的时候去掉,因为NSZombieEnabled不会真正去释放dealloc对象的内存,一直开启后果自负!

猜你喜欢

转载自blog.csdn.net/u010462316/article/details/79639760