xcode + lldb简单的调试

本文介绍了如何使用Xcode的内置调试器LLDB进行程序调试,包括初识LLDB、常用命令如help、print、expr、call、bt和image的使用方法,以及如何解决在调试过程中遇到的问题。通过学习,开发者可以更有效地在Xcode中进行代码调试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

~~~~我的生活,我的点点滴滴!!




昨天尝试着使用xcode调试一下程序,发现一个巨大的坑,坑到我实在忍无可忍(虽然不止这一个坑),Objective-C到处可见的@property

但是在xcode里面调试时根本就看不到里面的变量的值,这实在不可容忍,后来冷静下来一想,我就不信苹果的coder都不需要看这个值的。


google一下,后来发现xcode并没有像vs那样的直观可以直接显示出来,要使用LLDB的命令行来查看,虽然没那么直观,但是可能考虑到

coder不用离开键盘的原因才这样设计的,仔细想想其实也不错的,那么下面我们就收集整理一下这些调试技巧与命令吧。


随着Xcode 5的发布,LLDB调试器已经取代了GDB,成为了Xcode工程中默认的调试器。它与LLVM编译器一起,带给我们更丰富的流程控制和

数据检测的调试功能。LLDB为Xcode提供了底层调试环境,其中包括内嵌在Xcode IDE中的位于调试区域的控制面板,在这里我们可以直接调

用LLDB命令。如图所示:





我们不需要记住那么多的命令,只需要记住几个重要且xcode没有直接提供的命令就行了。




一、初识LLDB



你可能从未使用过LLDB,那让我们先来热热身。 在调试器中最常用到的命令是p(用于输出基本类型)或者po(用于输出 Objective-C 对象)。

如下,你可以通过输入po 和 view 来输出 view 的信息:

//1
po [self view]


//2
po [note fireDate]


//3
po dic



上面第一个输出会调用view这个object的description,你可能会看到很多像地址的内容:

(UIView *) $1 = 0x0824c800 <UITableView: 0x824c800; frame = (0 20; 768 1004); clipsToBounds = YES; autoresize = W+H; 
gestureRecognizers = <NSArray: 0x74c3010>; layer = <CALayer: 0x74c2710>; contentOffset: {0, 0}>

上面第二个输出中 fireDate为note的@property,直接在xcode中无法显示其值的,使用这种方式可以打印出来@property中变量的值

上面第三个输出中 dic是一个NSDictionary字典,也是在xcode中直接看不到里面的内容的,使用po很方便的打印出来所有的值,唯一

可以不爽的是如果NSDictionary里面的内容特别多,那就会占用很多空间(凑合用用吧)。

那么有人会问,这个命令在哪输入了?看下图:



现在知道在什么地方输入了吧。


你可能需要的是 view 下 subview 的数量。由于 subview 的数量是一个 int 类型的值,所以我们使用命令p:

//1
p (int)[[[self view] subviews] count] 



最后你看到的输出会是:


//1
(int) $2 = 2 


是不是很简单?

细心的朋友可能会发现输出的信息中带有$1、$2的字样。实际上,我们每次查询的结果会保存在一些持续变量中($[0-9]+),

这样你可以在后面的查询中直接使用这些值。比如现在我接下来要重新取回$1的值:

//1
po $1

依然可以看到我们之前使用 po [self view] 的值。


二、常见命令



2.1、help

最简单命令是 help,它会列举出所有的命令。如果你忘记了一个命令是做什么的,或者想知道更多的话,你可以通过 help来了

解更多细节,例如 help print 或者 help thread。如果你甚至忘记了 help 命令是做什么的,你可以试试 help help。



2.2、 print(po、p等的缩写)


打印值很简单;只要试试 print 命令:




LLDB 实际上会作前缀匹配。所以你也可以使用 prin,pri,或者 p。但你不能使用 pr,因为 LLDB 不能消除和 process 的歧

义 (幸运的是 p 并没有歧义)。


你可能还注意到了,结果中有个 $0。实际上你可以使用它来指向这个结果。试试 print $0 + 7,你会看到 106。任何以美元符

开头的东西都是存在于 LLDB 的命名空间的,它们是为了帮助你进行调试而存在的,在上面已经介绍过了。


2.3、expr (e、exp等缩写)

可以在调试时动态执行指定表达式,并将结果打印出来。常用于在调试过程中修改变量的值。





如图设置断点,然后运行程序。程序中断后输入下面的命令:

//1
expr a=2 


你会看到如下的输出:

//1
(int) $0 = 2 


继续运行程序,程序输出的信息是:

//1
实际值:2 


很明显可以看出,变量a的值被改变。 除此之外,还可以使用这个命令新声明一个变量对象,如:

//1
expr int $b=2 p $b 


下面的命令用于输出新声明对象的值。(注意,对象名前要加$)。



2.4、call

call即是调用的意思。其实上述的po和p也有调用的功能。因此一般只在不需要显示输出,或是方法无返回值时使用call。 和上

面的命令一样,我们依然在viewDidLoad:里面设置断点,然后在程序中断的时候输入下面的命令:

//1
call [self.view setBackgroundColor:[UIColor redColor]] 


继续运行程序,看看view的背景颜色是不是变成红色的了!在调试的时候灵活运用call命令可以起到事半功倍的作用。



2.5、bt

打印调用堆栈,加all可打印所有thread的堆栈。不详细举例说明,感兴趣的朋友可以自己试试。




2.6、image

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

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


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




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

我们可以输入以下的命令:

image lookup --address 0x0000000100004af8 


命令执行后返回:


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


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


很多时候,LLDB完整的命令是很长的。比如前面所说的image lookup --address这个组合命令。为了方便日常的使用,

提高效率,LLDB命令也提供通过简称的方式调用命令。还是这个命令,我们用简称就可以写为

im loo -a

是不是简单多了。如果你是从gdb时代就开始使用调试器的,你会发现,有些命令如p、call等命令和gdb下是一致的。其实这些命

令是LLDB一些命令的别名,比如p是frame variable的别名,p view实际上是frame variable view。除了系统自建的LLDB别名,

你也可以自定义别名,比如下面这个命令:

command alias ioa image lookup --address %1 

是将我前面所介绍过的一个命令image lookup --address添加了一个ioa的别名。然后执行下面的命令:

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


可以看到,我们得到了我们想要的结果,而命令却大大缩短。


三、常见问题



上面我们简单的学习了如何使用LLDB命令。但有时我们在使用这些LLDB命令的时候,依然可能会遇到一些问题,比如下面这个命令


(lldb) p NSLog(@"%@",[self.view  viewWithTag:1001]) 
error: 'NSLog' has unknown return type; cast the call to its declared return type error: 1 errors parsing expression 

如果在使用LLDB命令中发现有 unknown type 的类似错误(多见于id类型,比如NSArray中某个值,或者返回值),那我们就必须显

式声明类型。比如上面这个命令,我们得这么修改。

p (void)NSLog(@"%@",[self.view  viewWithTag:1001]) 

这样就能得到正确的结果了。


大部分时间我只要使用p、po等命令配合xcode提供的UI就够用了。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值