LLDB是个开源的内置于XCode的调试工具,这里来理一理常用用法。
lldb对于命令的简称,是头部匹配方式,只要不混淆,你可以随意简称某个命令。结果为在xcode下验证所得,可能与其它平台有所误差。

1 打印值、修改值、调用方法

1.1 p、po 打印值

打印相关的命令有:p、po。
p 和 po 的区别在于使用 po 只会输出对应的值,而 p 则会返回值的类型以及命令结果的引用名。

  1. (lldb) p width
  2. (CGFloat) $10 = 70
  3. (lldb) po width
  4. 70
  5. (lldb) p endTime
  6. (__NSCFString *) $14 = 0x0000608000437660 @"08-11 11:43"
  7. (lldb) po endTime
  8. 08-11 11:43

对比结果:

po:输出值
p:输出值+值类型+引用名+内存地址(xcode中有内存地址,其它平台不确定)
除此之外,p还隐藏了一个有意思的功能,常量的进制转换:

  1. //默认打印为10进制
  2. (lldb) p 100
  3. (int) $8 = 100
  4. //转16进制
  5. (lldb) p/x 100
  6. (int) $9 = 0x00000064
  7. //转8进制
  8. (lldb) p/o 100
  9. (int) $10 = 0144
  10. //转二进制
  11. (lldb) p/t 100
  12. (int) $2 = 0b00000000000000000000000001100100
  13. //字符转10进制数字
  14. (lldb) p/d 'A'
  15. (char) $7 = 65
  16. //10进制数字转字符
  17. (lldb) p/c 66
  18. (int) $10 = B\0\0\0

1.2 expression 修改参数值

感觉exp命令是调试过程中最有价值有命令了,它可以打印值、修改值。

  1. //expression打印值
  2. (lldb) expression width
  3. (CGFloat) $5 = 67
  4. //expression修改值
  5. (lldb) expression width = 80
  6. (CGFloat) $6 = 80
  7. //打印修改后结果
  8. (lldb) p width
  9. (CGFloat) $7 = 80
  10. (lldb)

expression:同样可以输出值+值类型+引用名,但其一般用于修改。

1.3 call 方法调用

在断点调用某个方法,并输出此方法的返回值。

  1. (lldb) call width
  2. (CGFloat) $12 = 70
  3. (lldb) call endTime
  4. (__NSCFString *) $16 = 0x0000608000437660 @"08-11 11:43"

call:同样为输出值+值类型+引用名

2 Thread

2.1 堆栈打印 thread backtrace

如果嫌堆栈打印太长,可以加一个值限制,如bt 10,只打印

  1. (lldb) bt 10
  2. * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  3.  * frame #0: 0x00000001005e4906 DiDi`-[FW_HomeCell_HotBill setDataSource:](self=0x00007fd3938a7800, _cmd="setDataSource:", dataSource=0x00006080001c8bb0) at FW_HomeCell.m:357
  4.    frame #1: 0x00000001009a9fd7 DiDi`-[FW_MyHomeTableView tableView:cellForRowAtIndexPath:](self=0x00007fd3921fec00, _cmd="tableView:cellForRowAtIndexPath:", tableView=0x00007fd3921fec00, indexPath=0xc000000000000316) at FW_MyHomeTableView.m:247
  5.    frame #2: 0x00000001055a2ab2 UIKit`-[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 750
  6.    frame #3: 0x00000001055a2cf8 UIKit`-[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
  7.    frame #4: 0x0000000105577639 UIKit`-[UITableView _updateVisibleCellsNow:isRecursive:] + 2845
  8.    frame #5: 0x00000001055abccc UIKit`-[UITableView _performWithCachedTraitCollection:] + 111
  9.    frame #6: 0x0000000105592e7a UIKit`-[UITableView layoutSubviews] + 233
  10.    frame #7: 0x00000001054f955b UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1268
  11.    frame #8: 0x0000000105114904 QuartzCore`-[CALayer layoutSublayers] + 146
  12.    frame #9: 0x0000000105108526 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 370

2.2 thread return 跳出当前方法的执行

Debug的时候,也许会因为各种原因,我们不想让代码执行某个方法,或者要直接返回一个想要的值。这时候就该thread return上场了。
有返回值的方法里,如:numberOfSectionsInTableView:,直接thread return 10,就可以直接跳过方法执行,返回10.

  1. //跳出方法
  2. (lldb) thread return
  3. //让带有返回int值的方法直接跳出,并返回值10
  4. (lldb) thread return 10

2.3 流程控制

实际上使用xcode自带的可视化工具来控制“继续”“暂停”“下一步”“进入”“跳出”更简单

  1. 继续:continue, c
  2. 下一步:next, n
  3. 进入:step, s
  4. 跳出:finish, f

2.4 跳帧 frame select N

2.1中打印有10帧,如果我想跳转到第1帧:frame select 1

  1. (lldb) frame select 1
  2. frame #1: 0x0000000105e91c3c DiDi`-[FW_HomeViewController tableView:cellForRowAtIndexPath:](self=0x00007fbf9f73b410, _cmd="tableView:cellForRowAtIndexPath:", tableView=0x00007fbfa11dc400, indexPath=0xc000000000a00316) at FW_HomeViewController.m:597
  3.   594                  break;
  4.   595                  
  5.   596                  case 3: {
  6. -> 597                      cell.[4md[0mataSource = _hotBills[indexPath.row];
  7.   598                      cell.textSelect = ^(UITextField *text) {
  8.   599                          weakSelf.curruntText = text;
  9.   600                      };

2.5 查看帧变量 frame variable

  1. (lldb) frame variable
  2. (FW_HomeViewController *) self = 0x00007faccbf587d0
  3. (SEL) _cmd = "tableView:cellForRowAtIndexPath:"
  4. (UITableView *) tableView = 0x00007faccd09b400
  5. (NSIndexPath *) indexPath = 0xc000000000000316
  6. (FW_HomeViewController *) weakSelf = 0x00007faccbf587d0
  7. (FW_HomeCell_HotBill *) cell = 0x00007faccc101a00
  8. (UIView *) model = 0x00007fff52c13d90
  9. (FW_HomeCell_HotBill *) billCell = 0x00000001124e99f6

3 Image

3.1 image lookup -address 查找崩溃位置

当你遇见数组崩溃,你又没有找到崩溃的位置,只扔给你一堆报错信息,这时候image lookup来帮助你。如下

  1. 0   CoreFoundation                      0x0000000103209b0b __exceptionPreprocess + 171
  2.    1   libobjc.A.dylib                     0x00000001079db141 objc_exception_throw + 48
  3.    2   CoreFoundation                      0x000000010313effb -[__NSArrayM objectAtIndex:] + 203
  4.    3   DiDi                                0x00000001009a9f3a -[FW_MyHomeTableView tableView:cellForRowAtIndexPath:] + 1322
  5.    4   UIKit                               0x00000001055a2ab2 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 750
  6.    5   UIKit                               0x00000001055a2cf8 -[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
  7.    6   UIKit                               0x0000000105577639 -[UITableView _updateVisibleCellsNow:isRecursive:] + 2845
  8.    7   UIKit                               0x00000001055abccc -[UITableView _performWithCachedTraitCollection:] + 111
  9.    8   UIKit                               0x0000000105592e7a -[UITableView layoutSubviews] + 233
  10.    9   UIKit                               0x00000001054f955b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1268
  11.    10  QuartzCore                          0x0000000105114904 -[CALayer layoutSublayers] + 146

寻找自己项目的标识,看到frame3位置,你只需这样查找位置:

  1. image lookup -a 0x00000001009a9f3a
  2.      Address: DiDi[0x0000000100609f3a] (DiDi.__TEXT.__text + 6323194)
  3.      Summary: DiDi`-[FW_MyHomeTableView tableView:cellForRowAtIndexPath:] + 1322 at FW_MyHomeTableView.m:243

项目中FW_MyHomeTableView.m:243,perfect!

3.2 image lookup -name 查找方法来源

此命令可以用来查找方法的来源。包括在第三方SDK中的方法,也能被查到。
例:查找transformOtherModelToSuit:

  1. (lldb) image lookup -n transformOtherModelToSuit:
  2. 1 match found in /Users/xxx/Library/Developer/Xcode/DerivedData/DiDi-cwpbvvyvqmeijmcjnneothzuthsy/Build/Products/Debug-iphonesimulator/DiDi.app/DiDi:
  3.        Address: DiDi[0x0000000100293d60] (DiDi.__TEXT.__text + 2693664)
  4.        Summary: DiDi`+[FW_BetFunction transformOtherModelToSuit:] at FW_BetFunction.m:107

3.3 image lookup –type 查看成员

查看某个class的所有属性和成员变量。不过貌似frameWork库中文件不能查看。

  1. (lldb) image lookup -t MatchEvent
  2. 1 match found in /Users/xxxx/Library/Developer/Xcode/DerivedData/DiDi-cwpbvvyvqmeijmcjnneothzuthsy/Build/Products/Debug-iphonesimulator/DiDi.app/DiDi:
  3. id = {0x00433d32}, name = "MatchEvent", byte-size = 48, decl = MatchEvent.h:11, compiler_type = "@interface MatchEvent : NSObject{
  4.    BOOL _isHome;
  5.    NSString * _playerName;
  6.    NSString * _timePoint;
  7.    NSString * _eventType;
  8.    NSString * _eventDesc;
  9. }
  10. @property ( getter = isHome,setter = setIsHome:,assign,readwrite,nonatomic ) BOOL isHome;
  11. @property ( getter = playerName,setter = setPlayerName:,readwrite,copy,nonatomic ) NSString * playerName;
  12. @property ( getter = timePoint,setter = setTimePoint:,readwrite,copy,nonatomic ) NSString * timePoint;
  13. @property ( getter = eventType,setter = setEventType:,readwrite,copy,nonatomic ) NSString * eventType;
  14. @property ( getter = eventDesc,setter = setEventDesc:,readwrite,copy,nonatomic ) NSString * eventDesc;
  15. @end"

4 breakpoint

4.1 文件名+行号 breakpoint set -f xxx -l xxx

我们平时操作xcode,在某一行点下断点,其实操作的就是这个命令。

  1. (lldb) breakpoint set -f FW_ProfilesDetailModel.m -l 95
  2. Breakpoint 3: where = DiDi`-[FW_ProfilesDetailModel incomeRate] + 27 at FW_ProfilesDetailModel.m:96, address = 0x0000000105b404bb

4.2 函数名断点

4.2.1 方法名断点 breakpoint set -n 方法名

  1. (lldb) breakpoint set -n viewDidLoad
  2. Breakpoint 4: 414 locations.

Tips:这里要说一下,xcode其实也有函数名断点,不过用breakpoint set -n实现,比xcode下断点快N倍,不过xcode下的断点还给提示所有断到的位置。

4.2.2 类中方法断点 breakpoint set -n “-[类名 方法名]”

  1. (lldb) breakpoint set -n "-[FW_MyHomeViewController viewDidLoad]"
  2. Breakpoint 8: where = DiDi`-[FW_MyHomeViewController viewDidLoad] + 20 at FW_MyHomeViewController.m:58, address = 0x0000000105aec944

注意:-[FW_MyHomeViewController viewDidLoad],外面一定要加双引

号,不然会误识别为-[FW_MyHomeViewController`

4.3 条件断点 breakpoint set -c “xxxx”

和xcode中symbolic Breakpoint功能相同,我在FW_HomeCell.m 362行下断点,但又想过滤仅width>68的状态,操作如下:

  1. breakpoint set -f FW_HomeCell.m -l 362 -c "width > 68"
  2. Breakpoint 5: where = DiDi`-[FW_HomeCell_HotBill setDataSource:] + 2006 at FW_HomeCell.m:363, address = 0x000000010d22e0a6

4.4 查看断点列表 breakpoint list

  1. (lldb) breakpoint list
  2. Current breakpoints:
  3. 8: name = '-[FW_MyHomeViewController viewDidLoad]', locations = 1, resolved = 1, hit count = 2
  4. 8.1: where = DiDi`-[FW_MyHomeViewController viewDidLoad] + 20 at FW_MyHomeViewController.m:58, address = 0x0000000105aec944, resolved, hit count = 2
  5. 9: file = '/Users/xxxx/didi-ios/DiDi/FollowWinner/Model/FW_HomeModel.m', line = 24, exact_match = 0, locations = 1, resolved = 1, hit count = 0
  6. 9.1: where = DiDi`+[FW_HomeModel_Rank parasWithDict:limitNickLength:] + 89 at FW_HomeModel.m:24, address = 0x00000001061bc169, resolved, hit count = 0

4.5 禁用/启用断点 breakpoint disable/enable

  1. //禁用断点
  2. (lldb) breakpoint disable 9
  3. 1 breakpoints disabled.
  4. (lldb) breakpoint list
  5. Current breakpoints:
  6. 9: file = '/Users/zmz/didi-ios/DiDi/FollowWinner/Model/FW_HomeModel.m', line = 24, exact_match = 0, locations = 1 Options: disabled
  7. 9.1: where = DiDi`+[FW_HomeModel_Rank parasWithDict:limitNickLength:] + 89 at FW_HomeModel.m:24, address = 0x00000001061bc169, unresolved, hit count = 0
  8. //启用断点
  9. (lldb) breakpoint enable 9
  10. 1 breakpoints enabled.
  11. (lldb) breakpoint list
  12. Current breakpoints:
  13. 9: file = '/Users/zmz/didi-ios/DiDi/FollowWinner/Model/FW_HomeModel.m', line = 24, exact_match = 0, locations = 1, resolved = 1, hit count = 0
  14. 9.1: where = DiDi`+[FW_HomeModel_Rank parasWithDict:limitNickLength:] + 89 at FW_HomeModel.m:24, address = 0x00000001061bc169, resolved, hit count = 0

4.6 移除断点 breakpoint delete

  1. (lldb) breakpoint delete 8
  2. 1 breakpoints deleted; 0 breakpoint locations disabled.
  3. (lldb) breakpoint list
  4. Current breakpoints:
  5. 9: file = '/Users/xxxx/didi-ios/DiDi/FollowWinner/Model/FW_HomeModel.m', line = 24, exact_match = 0, locations = 1, resolved = 1, hit count = 0
  6. 9.1: where = DiDi`+[FW_HomeModel_Rank parasWithDict:limitNickLength:] + 89 at FW_HomeModel.m:24, address = 0x00000001061bc169, resolved, hit count = 0

结语:

有了这些命令,调试起来肯定就得心应手了。总结下常用的,供多看几遍加深回忆:

堆栈相关:bt查看堆栈、frame select跳帧、frame variable查看帧参数、thread return跳出当前执行、【step/finish/next/continue】进入/跳出/下一步/跳出本断点

断点相关:breakpoint set -f -l -c条件断点、breakpoint set -n方法断点、breakpoint delete断点移除、breakpoint list断点列表

image命令:image lookup -address崩溃定位、image lookup -name方法来源、 image lookup –type 查看成员

LLDB支持简写

iOS之LLDB常用调试命令的更多相关文章

  1. gdb常用调试命令

    一般来说,GDB主要帮忙你完成下面四个方面的功能: 1.启动你的程序,可以按照你的自定义的要求随心所欲的运行程序.    2.可让被调试的程序在你所指定的调置的断点处停住.(断点可以是条件表达式)   ...

  2. GDB常用调试命令以及多进程多线程调试

    http://blog.csdn.net/freeelinux/article/details/53700266 一:普通命令   1.list命令 list  linenum      显示程序第l ...

  3. GDB常用调试命令(一)

    GDB是UNIX及UNIX-like下的调试工具,通常gdb使用前置条件:编译时加入debug信息,这里指的是C++. gcc/g++调试选项   gcc/g++是在编译时加入-g,-g分4个等级: ...

  4. gdb常用调试命令以及多线程堆栈的查看

    GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.或许,各位比较喜欢那种图形界面方式的,像VC.BCB等IDE的调试,但如果你是在UNIX平台下做软件,你会发现GDB这个调试工具有比VC ...

  5. GDB常用调试命令(二)

    GDB信号处理 在GDB中使用handle命令定义一个信号处理.信号可以以SIG开头或不以 SIG开头,可以用定义一个要处理信号的范围(如:SIGIO-SIGKILL,表示处理从SIGIO信号到SIG ...

  6. puppet常用调试命令

    yum快速部署puppet测试环境(C/S端) rpm -ivh  http://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm yum r ...

  7. gdb 常用调试命令

    1.   file    quit 2.   frame bt 3.   finish 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数信息. until 当要退出在一个循环体 ...

  8. squid常用调试命令

    解压,编译,make ,make install 就不说了.从 make install 后开始.当你的 squid.conf 配置文档按照你的想法修改完以后,启动 squid 之旅就开始了.1,初始 ...

  9. npm和yarn常用调试命令

    yarn查看全局安装路径 yarn global dir npm查看所有全局安装的包<全局路径也会显示> npm list --depth=0 -global

随机推荐

  1. Java的运行原理

    在Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器.这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口.编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由 ...

  2. 用python开发调试器——起始篇

    首先,你得准备一套python开发环境,正常情况下,一般是在windows下开发的,因为win系统应用广泛,再则就是要有个IDE,这里我选择我熟悉的Eclipse.环境搭建,网上都有,比如:http: ...

  3. Day6_正则表达式

    用作匹配数据的方法: print(re.findall('\w','yangshuai 123 asd \n \t')) #w:匹配字母数字下划线 print(re.findall('\W','yan ...

  4. 前端Mahsup异步依赖方式不能做业务数据依赖

    很久之前流行mashup方式做内容集成,之前为了IP定位的方便,引用了第三方的IP定位JS,然后根据其内容与服务器同步地址数据并写入Cookie,可是这种方式一旦,第三方的库反应缓慢时,就会出现大问题 ...

  5. C# SqlBulkCopy数据批量入库

    准备条件:20万+数据 界面设计使用的WPF. 没有对比就没有伤害,以下是我两种方式导入数据案例. 运行 结果对比: 首先使用一般sql语句导入,因为时间原因,我就没有等待程序执行完,但是我记录了大约 ...

  6. .net core使用Ku.Core.Extensions.Layui实现layui表单渲染

    演示网站地址:http://layui.kulend.com/项目地址:https://github.com/kulend/Ku.Core.Extensions/tree/master/Ku.Core ...

  7. 类的父类object的一些属性、方法

    # class Test: # """文档字符串""" # name = 'scolia' # # print(Test.__doc__) ...

  8. SQL Server性能优化(8)堆表结构介绍

    一.表结构综述 下图是SQL Server中表的组织形式(其中分区1.分区2是为了便于管理,把表进行分区,放到不同的硬盘数据文件里.默认情况下,表只有一个分区.).表在硬盘上的存放形式,有堆和B树两种 ...

  9. 3d轮播图——类似酷狗的轮播

    说到轮播图,其实只要是跟web开发相关的无论是前端后端应该都不陌生,各种各样的轮播图,从以前的单纯的平面山水画遮盖滑动或滚动,到Jquery的animate甚至是h5+css3,各种炫酷的轮播图更是层 ...

  10. java序列化反序列化深入探究(转)

    When---什么时候需要序列化和反序列化: 简单的写一个hello world程序,用不到序列化和反序列化.写一个排序算法也用不到序列化和反序列化.但是当你想要将一个对象进行持久化写入文件,或者你想 ...