深入了解GDB和LLDB

什么是GDB和LLDB

我们在开发iOS程序的时候常常会用到调试跟踪,如何正确的使用调试器来debug十分重要。xcode里有内置的Debugger,老版使用的是GDB,xcode自4.3之后默认使用的就是LLDB了。

GDB:
UNIX及UNIX-like下的调试工具。

LLDB:
LLDB是个开源的内置于XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安装C++或者Python插件。

所以他们两个都是调试用的Debugger,只是LLDB是比较高级的版本,或者在调试开发iOS应用时比较好用,不然人家苹果为什么换成了LLDB了呢!

lldb与gdb命令名的对照表:http://lldb.llvm.org/lldb-gdb.html

LLDB的使用

在程序里你需要的地方设置断点。当断点断住的时候你就能看到我们进入LLDB调试器了。

这时我们就可以使用一些LLDB命令来进行一些调试了。

调试快捷键:(Xcode常用快捷键)

command+shift+Y 打开调试窗口
command+Y 调试运行程序
command+option+P 继续
command+shift+O 跳过
command+shift+I 进入
command+shift+T 跳出

help命令

help会列出所有命令列表,用户加载的插件一般来说列在最后。
执行help 可以打印指定command的帮助信息。
比如:help print会打印内建命令print的使用帮助。

print命令

print命令的简化方式有prin pri p,唯独pr不能用来作为检查,因为会和process混淆,幸运的是p被lldb实现为特指print。

实际上你会发现,lldb对于命令的简称,是头部匹配方式,只要不混淆,你可以随意简称某个命令。

例如:

最前面的(int)是类型。$是命令结果的引用名,使用$0可以进行print $0 + 7这样打印出17。

输出view 下 subview 的数量。

由于 subview 的数量是一个 int 类型的值,所以我们使用命令p:
(lldb)p (int)[[[self view] subviews] count]

直接调用方法改变背景颜色之类

其实使用p,po,call都可以调用方法,只是p和po都是用于输出的有返回值的。call一般只在不需要显示输出,或是方法无返回值时使用。
(lldb)p [self.view setBackgroundColor:[UIColor redColor]]
(lldb)p (void)[CATransaction flush]
上述的p一般使用call比较好,因为方法是没有返回值的。

po命令

命令po跟p很像。p输出的是基本类型,po输出的Objective-C对象。调试器会输出这个 object 的 description。

例如:

expression命令

expression的简写就是e。可以用expression来声明新的变量,也可以改变已有变量的值。我们看到e声明的都是$开头的变量。我们在使用时也需要加上$符号。

例如:

创建新的变量


注意:如果上面这里输入以下命令,会发生错误。说明lldb无法判定某一步的计算结果是什么数据类型,这时需要强制类型转换来告诉lldb。

(lldb) p [[$array objectAtIndex:0] characterAtIndex:0]
error: no known method '-characterAtIndex:'; cast the message send to the method's return type
error: 1 errors parsing expression

(lldb) p (char)[[$array objectAtIndex:0] characterAtIndex:0]
'o'

修改已有变量

image命令

image 命令可用于寻址,有多个组合命令。比较实用的用法是用于寻找栈地址对应的代码位置。 下面我写了一段代码

NSArray *arr=[[NSArray alloc] initWithObjects:@"1",@"2", nil];
NSLog(@"%@",arr[2]);

这段代码有明显的错误,程序运行这段代码后会抛出下面的异常:

 *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
*** First throw call stack:
(
 0   CoreFoundation                      0x0000000101951495 __exceptionPreprocess + 165
 1   libobjc.A.dylib                     0x00000001016b099e objc_exception_throw + 43
2   CoreFoundation                      0x0000000101909e3f -[__NSArrayI objectAtIndex:] + 175
3   ControlStyleDemo                    0x0000000100004af8 -[RootViewController viewDidLoad] + 312
4   UIKit                               0x000000010035359e -[UIViewController loadViewIfRequired] + 562
5   UIKit                               0x0000000100353777 -[UIViewController view] + 29
6   UIKit                               0x000000010029396b -[UIWindow addRootViewControllerViewIfPossible] + 58
7   UIKit                               0x0000000100293c70 -[UIWindow _setHidden:forced:] + 282
8   UIKit                               0x000000010029cffa -[UIWindow makeKeyAndVisible] + 51
9   ControlStyleDemo                    0x00000001000045e0 -[AppDelegate application:didFinishLaunchingWithOptions:] + 672
10  UIKit                               0x00000001002583d9 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 264
11  UIKit                               0x0000000100258be1 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1605
12  UIKit                               0x000000010025ca0c -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 660
13  UIKit                               0x000000010026dd4c -[UIApplication handleEvent:withNewEvent:] + 3189
14  UIKit                               0x000000010026e216 -[UIApplication sendEvent:] + 79
15  UIKit                               0x000000010025e086 _UIApplicationHandleEvent + 578
16  GraphicsServices                    0x0000000103aca71a _PurpleEventCallback + 762
17  GraphicsServices                    0x0000000103aca1e1 PurpleEventCallback + 35
18  CoreFoundation                      0x00000001018d3679 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
19  CoreFoundation                      0x00000001018d344e __CFRunLoopDoSource1 + 478
20  CoreFoundation                      0x00000001018fc903 __CFRunLoopRun + 1939
21  CoreFoundation                      0x00000001018fbd83 CFRunLoopRunSpecific + 467
22  UIKit                               0x000000010025c2e1 -[UIApplication _run] + 609
23  UIKit                               0x000000010025de33 UIApplicationMain + 1010
24  ControlStyleDemo                    0x0000000100006b73 main + 115
25  libdyld.dylib                       0x0000000101fe95fd start + 1
26  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

现在,我们怀疑出错的地址是0x0000000100004af8(可以根据执行文件名判断,或者最小的栈地址)。为了进一步精确定位,我们可以输入以下的命令:

(lldb)image lookup --address 0x0000000100004af8
(lldb)im loo -a 0x0000000100004af8

命令执行后返回:

Address: ControlStyleDemo[0x0000000100004af8] (ControlStyleDemo.__TEXT.__text + 13288)
Summary: ControlStyleDemo`-[RootViewController viewDidLoad] + 312 at RootViewController.m:53

我们可以看到,出错的位置是RootViewController.m的第53行。

设置断点触发条件

参考

LLDB使用篇
LLDB调试命令初探

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • [转]浅谈LLDB调试器文章来源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc阅读 2,410评论 2 6
  • 你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值? NSLog(@"%@", whatIsInsideThi...
    paraneaeee阅读 1,129评论 0 7
  • 转载 与调试器共舞 - LLDB 的华尔兹: https://objccn.io/issue-19-2/ 推荐:i...
    F麦子阅读 3,281评论 0 10
  • LLDB的Xcode默认的调试器,它与LLVM编译器一起,带给我们更丰富的流程控制和数据检测的调试功能。平时用Xc...
    CoderSC阅读 1,304评论 0 2
  • 与调试器共舞 - LLDB 的华尔兹 nangege 2014/12/19 你是否曾经苦恼于理解你的代码,而去尝试...
    McDan阅读 870评论 0 0