关于LLDB调试你应该知道的
2015-04-07 13:58
363 查看
最近一直在与大家探讨LLDB调试的问题,最早是在objccn上看到--- 《与调试器共舞-LLDB的华尔兹》,深深的吸引了我,所以就深入研究学习,果然用的人不是很多啊,不过还是找了几篇不错的文章,转载来以供参考。
与调试器共舞-LLDB的华尔兹 http://objccn.io/issue-19-2/
原文地址一:http://www.jianshu.com/p/f888db82fc27
原文地址二:http://www.jianshu.com/p/b2371dd4443b
本来一直想给大家普及一下lldb的使用,因为身边有很多朋友虽然开发了很久,但是还是不会使用调试器,还傻傻的打一个log,重启程序再看这个值。说,是不是你,中招没。这一篇也是为了帮这些朋友认识一下调试器的强大。整篇介绍的例子都是基于我的贴图demo的。
如图下:
![](http://m2.img.srcdd.com/farm4/d/2015/0212/11/C27AE564FFD6FE8FC899F68DED134DD7_ORIG_1733_926.gif)
lldbLog
1.首先注释以前那该死的log背景被点击了,然后我加一个优美的断点。
2.然后右键点击断点编辑断点,首先选择Action,logMessage,再点击+,选择DebugerCommander,然后这里面的命令和右下角的lldb命令是完全一样的,这个命令你随意打。
3.最重要的一步,一点要选择automaticlly continue after evalating value,这个可以使得程序不会中断继续执行。
好吧,大家以后就可以告别这个该死的log,以后大家的consle就不出现那些乱七八糟的log,而且还找不到了.我现在就是每次看到项目里一堆log就特别烦……(ps:这个……是shift+6打出来的哦),所以只要你想在输出某一个值或者一句话看一个函数,是否调用,完全不需要多余的重新运行一次程序。
大家一般知道的lldb命令一般是p,和po,其实我研究了一阵子最实用的也就这两个lldb命令,但是大家一般都不知道用在什么场合。
p命令的介绍,首先p是打印非对象的值,它是 e --的缩写。如果使用它打印对象的话,那么它会打印出对象的地址,如果打印非对象它一般会打印出基本变量类型的值。当然用它也可以申明一个变量譬如 p int $a = 10; (注lldb使用$在变量前来声明为lldb内的命名空间的)
po 命令,po 命令是我们最常用的命令因为在ios开发中,我们时刻面临着对象(ps:但是我没有对象,欢迎介绍),所以我们在绝大部分时候都会使用po。首先po这个命令会打印出对象的description描述。
好吧,macDown语法还是没有完全搞明白,所以篇幅不是太好看(这个完全没想这么早出这篇博客)
下面还是使用一副图片来描述具体的过程吧。
![](http://m3.img.srcdd.com/farm4/d/2015/0212/13/E505902B1D8D75A1B63C5611BF482417_ORIG_1490_964.gif)
po的使用
1.首先我在背景蒙层下了个断点,程序中断之后,我首先通过po 命令打出了【po self.view】然后打出了当前的self.view的描述。
2.然后我通过self.view的description描述,然后找到手势NSArry的地址我打印出了当前view上面有那些手势。
然后找到当前pinch的手势,然后通过p 命令,将其强转成UIPinchGesture,因为lldb有时无法确定其具体的类型,需要强转,但是这个强转不是必须的,需要你们自己根据情况来决定。
当我们使用p 命令打印一个对象时,lldb内部会默认使用一个$加数字来记录这个对象。
这个$会一直存在,当这个对象还没销毁的时候,所以我们随时可以通过这个变量来打印以前的值。我是通过【$61 view】找出pinch 作用的view.我们也可以使用p 命令得到一个这个view在lldb的记录。
注意在使用lldb内部的变量$来记录变量的时候,绝大部分的时候都没有语法提示,所以你需要自己能准确的打印出方法的名字。我这里一般,都是在当前编辑器中去打好方法,然后再拷贝到lldb处。
在使用lldb命令的时候,并非所有的命令都很常用,你可以通过在lldb中 打印 help 查看所有的lldb命令,譬如breakpoint命令,这种命令完全可以通过Xcode UI界面加断点,当然所有的xcode ui 界面加断点本质也是通过lldb的命令的,这个一般用户都不会太常用。
![](http://m2.img.srcdd.com/farm4/d/2015/0212/13/2D9F83BA11E4F162D239E1742B7A4E3D_B500_900_500_634.png)
help命令
今天就先介绍到这里,下一篇博客我会介绍给大家如何使用开源的facebook的chisel,从安装到以及在什么场景下使用什么命令,和常用的chisel命令有哪些。因为这个MarkDown还没弄太熟悉,所以重头戏在下一章。(ps:主要是markDown还没用熟,我自己看着都不爽,所以下次会带来更好的版本,和更详细的介绍)
这次真是久违的第二篇了,过年的时候一直在帮家里带孩子,顺便用webStorm这个神器重新温习了下前端的知识。然后最近刚来北京又是重感冒,又是找房子,整个来说coding还是写博客效率极低又苦不堪言。
首先如果使用lldb,最好你要学着使用chisel来提高效率,否则你会浪费很多的时间,除非你自己会写python脚本,自己封装一些lldb的命令。
chisel的安装是十分简单,它是在终端通过brew安装的,具体可以点击链接参考github的安装说明,唯一需要注意的一点就是命令行安装完之后,它会在安装完之后显示出chisel的安装地址path.在执行下面的命令时候要记得替换/path/to/fblldb.py这一块。
如果安装成功的话,那么你就会看到如下图的这些命令。
![](http://m2.img.srcdd.com/farm4/d/2015/0308/22/E835901C12DB9A2018B1FF573B161069_B500_900_500_213.png)
lldb help
这里大概会有30个命令吧,我记得我第一次装的时候没那么多命令的,facebook又更新了很多。其实这些封装的命令,就是使用python封装了一下函数然后调用。凡是这些封装的命令,你都可以通过多个lldb命令打出来,所以如果你会使用python的话,那么你可以根据自己的使用习惯封装一些常用的lldb命令。我使用了也有一段时间的chisel了,但是感觉并不是所有的命令都很常用,而且有写使用的场景也不是很清楚,所以在这里给大家普及一下,如果有谬误,请大家及时指正。(ps:和大家说个快捷键,cmd+k快速清楚console的信息。)
一般我们使用chisel的命令的时候,我们可以通过 help + chisel命令,譬如 help + pvc,得到如何具体使用这个命令,但是有时候你看了help信息也不一定就会用呢。
![](http://m1.img.srcdd.com/farm5/d/2015/0308/22/11C139A4BF9F53F540953BB2F6B307B1_B500_900_500_160.png)
image
这个命令是我最常使用的命令。它能够帮助我们看到view的层级,即使我们并没有触发到一个断点。操作如下:
![](http://m2.img.srcdd.com/farm5/d/2015/0308/22/2032B982DBAF0EB09D1C49D01D64CD63_ORIG_938_714.gif)
pviews
如图我没有设置任何断点,只是点击控制台的暂停图标,就可以呼出lldb控制台了。然后再这里输出pviews这个命令。
然后这个命令主要可以看到当前的view层级,如果我们写了一个控件没有显示。我们就可以通过这个命令来排查。
排查首先看有没有我们添加的这个view,如button,如果内存地址里没有这个button,说明没有添加到view中(没调用addSubview方法)
然后可以看到这个button的地址,我们可以看到这个button的frame属性,根据属性判断是否是位置或者大小不合适。
再次,我们要看是否hidden被设置成了yes,如果设置了yes的话,在打印信息中会打印出来。因为默认view的isHidden是no,所以没被打印。
最后如果是button可以检查下是否设置了图片,如果是view,就可以查看下颜色是否与后面的控件一致,这就引入到了下一个命令border。
![](http://m3.img.srcdd.com/farm5/d/2015/0308/23/2FDA13630E75FB9AA1CD89CBE9B81597_B500_900_500_337.png)
border
这个命令可以直接给border 添加边框颜色和边框的宽度,使用如下:
border这个命令常常在我们需要查看边框的边缘的问题,常常用到,而且我们想要设置的直接在lldb中设置,完全不需要重新写代码再次运行。我就是通过直接暂停程序,并且通过pviews命令找到的控件的地址,并且调用命令显示的。当我们不需要的时候可以通过
![](http://m3.img.srcdd.com/farm4/d/2015/0308/23/9817F08BEB31BF19E4A374E2B26113B4_B500_900_500_682.png)
pinternals
这个命令就是打印出来的一个控件(
打印出一个集成于UIResponder控件的消息传递链。
![](http://m1.img.srcdd.com/farm4/d/2015/0308/23/08D1D5B28A97BC3CDB6C29A65F71C9FB_B500_900_500_377.png)
presponder
这个也方便我们了解消息是如何传递的,打印的时候是倒叙打印的。
可以使用mac下的预览app打开我们的图片UIImage, CGImageRef格式的图片,甚至view和layer的图片 。
pclass可以打印出一个对象的继承关系。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201912/08/92e7daf86fa1cc1785718303120e14ca)
pclass
这个命令是模拟敲击一下屏幕,并且打印出你敲击屏幕时候事件接收的对象。
![](http://m3.img.srcdd.com/farm4/d/2015/0308/23/F2F93B95D430C3270D65AC3405BE9327_B500_900_500_101.png)
image
hide命令可以直接隐藏一个对象,移除当前遮挡的对象便于你观察后面的对象。show命令会让它再次显示出来。
这个命令就是lldb添加一个断点,譬如-viewWillAppear:这个方法,在当前控制器中你没有实现它,但是你又想在调用它的时机触发中断。
Arguments:
<expression>; Type: string; Expression to set a breakpoint on, e.g. "-[MyView setFrame:]", "+[MyView awesomeClassMethod]" or "-[0xabcd1234 setFrame:]"
这个我就不解释了,需要补充一点的是oc的方法是带
其它命令我用着并不是太多,并不代表他们不常用。只是我用的不太好而已,而且我认为用到是需要特殊的场景的,这个里说几个我感觉有很大作用但是我用的又不好的。
南峰子的技术博客,工具篇:LLDB调试器
Dancing in the Debugger — A Waltz with LLDB
LLDB调试命令初探
Xcode LLDB Debug教程
我写的这些关于lldb的东西只是九牛一毛,它可以做的事情特别多,上面的参考都是我看过的比较好的lldb的知识,大家了解可以通过我上面的一些网站,更加深入的第三篇,我一时半会不会写的,因为那个才是真正的进阶,而我还没达到那种高度,如果你也有好的关于lldb的技巧,理解之类的,欢迎分享。
与调试器共舞-LLDB的华尔兹 http://objccn.io/issue-19-2/
原文地址一:http://www.jianshu.com/p/f888db82fc27
原文地址二:http://www.jianshu.com/p/b2371dd4443b
久违的的LLDB篇一,让lldb提升你的效率
本来一直想给大家普及一下lldb的使用,因为身边有很多朋友虽然开发了很久,但是还是不会使用调试器,还傻傻的打一个log,重启程序再看这个值。说,是不是你,中招没。这一篇也是为了帮这些朋友认识一下调试器的强大。整篇介绍的例子都是基于我的贴图demo的。
1.首先介绍下如何避免重启程序打一个log
如图下:![](http://m2.img.srcdd.com/farm4/d/2015/0212/11/C27AE564FFD6FE8FC899F68DED134DD7_ORIG_1733_926.gif)
lldbLog
1.首先注释以前那该死的log背景被点击了,然后我加一个优美的断点。
2.然后右键点击断点编辑断点,首先选择Action,logMessage,再点击+,选择DebugerCommander,然后这里面的命令和右下角的lldb命令是完全一样的,这个命令你随意打。
3.最重要的一步,一点要选择automaticlly continue after evalating value,这个可以使得程序不会中断继续执行。
好吧,大家以后就可以告别这个该死的log,以后大家的consle就不出现那些乱七八糟的log,而且还找不到了.我现在就是每次看到项目里一堆log就特别烦……(ps:这个……是shift+6打出来的哦),所以只要你想在输出某一个值或者一句话看一个函数,是否调用,完全不需要多余的重新运行一次程序。
2基本的lldb命令的介绍
大家一般知道的lldb命令一般是p,和po,其实我研究了一阵子最实用的也就这两个lldb命令,但是大家一般都不知道用在什么场合。p命令的介绍,首先p是打印非对象的值,它是 e --的缩写。如果使用它打印对象的话,那么它会打印出对象的地址,如果打印非对象它一般会打印出基本变量类型的值。当然用它也可以申明一个变量譬如 p int $a = 10; (注lldb使用$在变量前来声明为lldb内的命名空间的)
po 命令,po 命令是我们最常用的命令因为在ios开发中,我们时刻面临着对象(ps:但是我没有对象,欢迎介绍),所以我们在绝大部分时候都会使用po。首先po这个命令会打印出对象的description描述。
好吧,macDown语法还是没有完全搞明白,所以篇幅不是太好看(这个完全没想这么早出这篇博客)
下面还是使用一副图片来描述具体的过程吧。
![](http://m3.img.srcdd.com/farm4/d/2015/0212/13/E505902B1D8D75A1B63C5611BF482417_ORIG_1490_964.gif)
po的使用
1.首先我在背景蒙层下了个断点,程序中断之后,我首先通过po 命令打出了【po self.view】然后打出了当前的self.view的描述。
2.然后我通过self.view的description描述,然后找到手势NSArry的地址我打印出了当前view上面有那些手势。
然后找到当前pinch的手势,然后通过p 命令,将其强转成UIPinchGesture,因为lldb有时无法确定其具体的类型,需要强转,但是这个强转不是必须的,需要你们自己根据情况来决定。
当我们使用p 命令打印一个对象时,lldb内部会默认使用一个$加数字来记录这个对象。
这个$会一直存在,当这个对象还没销毁的时候,所以我们随时可以通过这个变量来打印以前的值。我是通过【$61 view】找出pinch 作用的view.我们也可以使用p 命令得到一个这个view在lldb的记录。
注意在使用lldb内部的变量$来记录变量的时候,绝大部分的时候都没有语法提示,所以你需要自己能准确的打印出方法的名字。我这里一般,都是在当前编辑器中去打好方法,然后再拷贝到lldb处。
在使用lldb命令的时候,并非所有的命令都很常用,你可以通过在lldb中 打印 help 查看所有的lldb命令,譬如breakpoint命令,这种命令完全可以通过Xcode UI界面加断点,当然所有的xcode ui 界面加断点本质也是通过lldb的命令的,这个一般用户都不会太常用。
![](http://m2.img.srcdd.com/farm4/d/2015/0212/13/2D9F83BA11E4F162D239E1742B7A4E3D_B500_900_500_634.png)
help命令
今天就先介绍到这里,下一篇博客我会介绍给大家如何使用开源的facebook的chisel,从安装到以及在什么场景下使用什么命令,和常用的chisel命令有哪些。因为这个MarkDown还没弄太熟悉,所以重头戏在下一章。(ps:主要是markDown还没用熟,我自己看着都不爽,所以下次会带来更好的版本,和更详细的介绍)
LLdb篇2教你使用faceBook的chisel来提高调试效率
这次真是久违的第二篇了,过年的时候一直在帮家里带孩子,顺便用webStorm这个神器重新温习了下前端的知识。然后最近刚来北京又是重感冒,又是找房子,整个来说coding还是写博客效率极低又苦不堪言。首先如果使用lldb,最好你要学着使用chisel来提高效率,否则你会浪费很多的时间,除非你自己会写python脚本,自己封装一些lldb的命令。
安装chisel
chisel的安装是十分简单,它是在终端通过brew安装的,具体可以点击链接参考github的安装说明,唯一需要注意的一点就是命令行安装完之后,它会在安装完之后显示出chisel的安装地址path.在执行下面的命令时候要记得替换/path/to/fblldb.py这一块。# ~/.lldbinit ... command script import /path/to/fblldb.py script fblldb.loadCommandsInDirectory('/magical/ commands/')
如果安装成功的话,那么你就会看到如下图的这些命令。
![](http://m2.img.srcdd.com/farm4/d/2015/0308/22/E835901C12DB9A2018B1FF573B161069_B500_900_500_213.png)
lldb help
这里大概会有30个命令吧,我记得我第一次装的时候没那么多命令的,facebook又更新了很多。其实这些封装的命令,就是使用python封装了一下函数然后调用。凡是这些封装的命令,你都可以通过多个lldb命令打出来,所以如果你会使用python的话,那么你可以根据自己的使用习惯封装一些常用的lldb命令。我使用了也有一段时间的chisel了,但是感觉并不是所有的命令都很常用,而且有写使用的场景也不是很清楚,所以在这里给大家普及一下,如果有谬误,请大家及时指正。(ps:和大家说个快捷键,cmd+k快速清楚console的信息。)
一般我们使用chisel的命令的时候,我们可以通过 help + chisel命令,譬如 help + pvc,得到如何具体使用这个命令,但是有时候你看了help信息也不一定就会用呢。
![](http://m1.img.srcdd.com/farm5/d/2015/0308/22/11C139A4BF9F53F540953BB2F6B307B1_B500_900_500_160.png)
image
pviews
这个命令是我最常使用的命令。它能够帮助我们看到view的层级,即使我们并没有触发到一个断点。操作如下:![](http://m2.img.srcdd.com/farm5/d/2015/0308/22/2032B982DBAF0EB09D1C49D01D64CD63_ORIG_938_714.gif)
pviews
如图我没有设置任何断点,只是点击控制台的暂停图标,就可以呼出lldb控制台了。然后再这里输出pviews这个命令。
然后这个命令主要可以看到当前的view层级,如果我们写了一个控件没有显示。我们就可以通过这个命令来排查。
排查首先看有没有我们添加的这个view,如button,如果内存地址里没有这个button,说明没有添加到view中(没调用addSubview方法)
然后可以看到这个button的地址,我们可以看到这个button的frame属性,根据属性判断是否是位置或者大小不合适。
再次,我们要看是否hidden被设置成了yes,如果设置了yes的话,在打印信息中会打印出来。因为默认view的isHidden是no,所以没被打印。
最后如果是button可以检查下是否设置了图片,如果是view,就可以查看下颜色是否与后面的控件一致,这就引入到了下一个命令border。
border&unborder
![](http://m3.img.srcdd.com/farm5/d/2015/0308/23/2FDA13630E75FB9AA1CD89CBE9B81597_B500_900_500_337.png)
border
这个命令可以直接给border 添加边框颜色和边框的宽度,使用如下:
border 0x79ec3140 -c green -w 2
border这个命令常常在我们需要查看边框的边缘的问题,常常用到,而且我们想要设置的直接在lldb中设置,完全不需要重新写代码再次运行。我就是通过直接暂停程序,并且通过pviews命令找到的控件的地址,并且调用命令显示的。当我们不需要的时候可以通过
unborder这个命令去掉边框。整个过程一气呵成。
pinternals
![](http://m3.img.srcdd.com/farm4/d/2015/0308/23/9817F08BEB31BF19E4A374E2B26113B4_B500_900_500_682.png)
pinternals
这个命令就是打印出来的一个控件(
id)类型的内部结构,详细到令人发指!甚至是你自定义的控件中的类型,譬如这个
styleView就是我自定义的,内部有个iconView的属性,其中的值它也会打印出来。好处,你们自己琢磨吧。(ps:这个demo,我会在下一篇博客中放出来,下篇博客是说transform的。
presponder
打印出一个集成于UIResponder控件的消息传递链。![](http://m1.img.srcdd.com/farm4/d/2015/0308/23/08D1D5B28A97BC3CDB6C29A65F71C9FB_B500_900_500_377.png)
presponder
这个也方便我们了解消息是如何传递的,打印的时候是倒叙打印的。
visualize
可以使用mac下的预览app打开我们的图片UIImage, CGImageRef格式的图片,甚至view和layer的图片 。visualize 0x79ec3140//或者变量名,此地址是id类型的
pclass
pclass可以打印出一个对象的继承关系。pclass
taplog
这个命令是模拟敲击一下屏幕,并且打印出你敲击屏幕时候事件接收的对象。![](http://m3.img.srcdd.com/farm4/d/2015/0308/23/F2F93B95D430C3270D65AC3405BE9327_B500_900_500_101.png)
image
hide&show
hide命令可以直接隐藏一个对象,移除当前遮挡的对象便于你观察后面的对象。show命令会让它再次显示出来。
bmessage
这个命令就是lldb添加一个断点,譬如-viewWillAppear:这个方法,在当前控制器中你没有实现它,但是你又想在调用它的时机触发中断。Arguments:
<expression>; Type: string; Expression to set a breakpoint on, e.g. "-[MyView setFrame:]", "+[MyView awesomeClassMethod]" or "-[0xabcd1234 setFrame:]"
这个我就不解释了,需要补充一点的是oc的方法是带
:的。
其他命令
其它命令我用着并不是太多,并不代表他们不常用。只是我用的不太好而已,而且我认为用到是需要特殊的场景的,这个里说几个我感觉有很大作用但是我用的又不好的。wivar,这个命令是加watchPoint,用的好,就相当于使用lldb写了kvo了。(ps:恕我没研究明白)
pvc这个命令的作用是打印出当前的控制器层级,(ps:有时好使,有时又很坏,似魔鬼的步伐.?,没研究明白)
vs,
fv,
fvc,这几个命令都需要正则表达式的知识背景,因为我正则表达式从来都是百度,也没自己真正学过。所以对我不常用,但是对那些会正则的可能会很大作用。(ps:希望你们研究出来有什么好的技巧分享下)
参考
南峰子的技术博客,工具篇:LLDB调试器Dancing in the Debugger — A Waltz with LLDB
LLDB调试命令初探
Xcode LLDB Debug教程
我写的这些关于lldb的东西只是九牛一毛,它可以做的事情特别多,上面的参考都是我看过的比较好的lldb的知识,大家了解可以通过我上面的一些网站,更加深入的第三篇,我一时半会不会写的,因为那个才是真正的进阶,而我还没达到那种高度,如果你也有好的关于lldb的技巧,理解之类的,欢迎分享。
相关文章推荐
- 关于薪资问题你应该知道的
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情-Java基础-Java-编程开发
- 作为一个程序员,有些知识你应该知道----关于并发和数据库封锁
- 关于J2ME,应该知道的事
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情
- 关于 JavaBean 规范你还是应该知道的二三事
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情
- 关于SPECjAppServer评测,您应该知道的“故事”
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情
- 你应该知道的10件关于Java 6的事情
- 关于 JavaBean 规范你还是应该知道的二三事