iOS开发——测试篇&breakpoints、lldb 和 chisel 的详解
breakpoints、lldb 和 chisel 的详解
Breakpoints
BreakPoint分类
breakpoint也是有分类的,我这里的文章内大致按使用的方式分为了
- Normal Breakpoint,
- Exception Breakpoint,
- OpenGL ES Error breakpoint,
- Symbolic Breakpoint,
- Test Failure Breakpoint,
- WatchPoints。
可以按具体的情景使用不同类型的breakpoint,解决问题为根本。
Normal Breakpoint
添加普通断点就不多说了,在源代码的右侧点击一下即可。或者,使用快捷键:command + \ 来添加和删除。这两种方式添加的breakpoints在Xcode上面是可以通过UI看到的。
还有可以通过下面两个LLDB命令直接在运行时添加断点,但是这种方式需要注意的是一方面无法通过UI直接看到断点,另外一方面只存在于本次运行,下一次启动模拟器重新运行的时候,这些断点就不生效了。
如上图,通过“br li”命令打印所有的breakpoint,可以看到一共有3个breakpoint,第一个是通过Xcode的UI添加的,后面两个分别是通过下面两个命令添加的:
“breakpoint set -f XXX.m -l XX” 和 “b XXX.m:XX”。
Exception Breakpoint
可以通过下图中Xcode的UI添加Exception Breakpoint。有时候,比如数组越界或者设置一个空对象等问题,都会抛出一个异常,但是这种类型的错误非常难以定位,这个时候就可以使用Exception Breakpoint来进行调试,在异常发生时可以捕捉到并停止程序的执行。OC中的异常是一个常被忽略的地方,但实际上系统框架内这个使用非常广泛,大部分这种错误信息,系统框架都会以异常的形式throw出来,所以善用这种breakpoint的话,我们能大大减少查找错误的时间。
例如,当我们添加如下Exception Breakpoint之后(bt 命令后文中会讲解,这个命令的作用是在断点触发时,打印回调栈信息):
类似下面这样的数组越界的问题,我们可以很容易就定位到问题所在,不用再毫无头绪找来找去了:
当断点暂停执行时,我们可以通过Xcode的UI中查看调用栈信息:
或者查看bt命令打印的调用栈信息:
还有类似如下的错误可以通过这种断点很容易定位到:
,不过这种问题,可以通过使用setValue:forKey:代替来避免。
OpenGL ES Error Breakpoint
同上图中,在Xcode的breakpoint navigator的下部添加按钮,选择”Add OpenGL ES Error Breakpoint”即可。这个breakpoint主要是用来在OpenGL ES发生错误时停止程序的运行。
Symbolic Breakpoint
通过Xcode的UI添加symbolic breakpoint的方式同exception breakpoint,弹出框如下:
Symbolic breakpoints 在某个特定的函数或者方法开始执行的时候,暂停程序的执行,通过这种方式添加断点,我们就不需要知道在源文件中添加,也不需要知道断点设置在文件的第几行。
上图中,最主要的设置是Symbol的内容,可以有如下几种:
- 1. A method name,方法名称,例如 pathsMatchingExtensions: 这样的方法名称,会对所有类的这个方法都起作用。
- 2. A method of a particular class. 特定类的某个方法。例如 ,[SKLine drawHandlesInView],或者 people::Person::name()
- 3. A function name。函数名称。例如 ,_objc_msgForward 这样C函数。
另外,也可以通过命令行的方式添加 Symbolic breakpoints。对C函数添加断点:
对OC的方法添加断点:
常用的这个类型的断点有,objc_exception_throw可以用来代替 Exception Breakpoint,还有一个-[NSObject doesNotRecognizeSelector:] 也比较常用,用于检测方法调用失败。
Test Failure Breakpoint
通过Xcode的UI添加方法同上。这个类型的break point 会在 test assertion 失败的时候暂停程序的执行。
Watchpoints
Watuchpoints是一个用来监听变量的值的变化或者内存地址的变化的工具,发生变化时会在debugger中触发一个暂停。对于那些不知道如何准确跟踪的状态问题,可以利用这个工具来解决。要设置watchpoint的话,在程序运行到stack frame包含有你想观察的变量时,让debugger暂停运行,这个时候变量在当前stack frame的scope内,这个时候才能对该变量设置watchpoint。
你可以在Xcode的GUI中设置watchpoint,在xcode的 Variables View中,把你想观察的变量保留出来,然后右键设置“Watch XXX”。例如下图,观察self的title变量,点击 Watch “_button1ClickCount” 即可。
命令行
或者也可以通过命令行来设置watchpoint:watch set variable _button1ClickCount,详细命令可以参考:http://lldb.llvm.org/lldb-gdb.html,有好几种命令可以达到同样的效果。
上面是对变量进行观察,实际上我们可以对任意内存地址进行观察,命令如下:watchpoint set expression — 0x123456,参考:http://stackoverflow.com/questions/21063995/watch-points-on-memory-address
需要注意的是,watchpoint是分类型的,包括read,write或者read_write类型,这个非常容易理解,在读,写或者读写变量或内存的时候,watchpoint是否被触发。read,write或read_write跟着-w参数后面表示类型。另外,命令行中,watchpoint还有一些简写,set简写为s,watch简写为wa,variable简写为v。
下面的示例是来自 http://www.dreamingwish.com/article/lldb-usage-a.html 网站的几个命令:
第一个命令是监听_abc4变量的内存地址write的变化,第二个是监听_abc4变量read的变化,第三个是监听_abc3变量read_write的变化。
需要注意的是,通过Xcode的GUI添加的watchpoint为默认类型,即write类型,如果想要添加读写都watch的watchpoint,则只能通过命令行工具进行添加了。
使用watchpoint modify -c ‘(XXX==XX)’,则修改watchpoint之后在某个值的时候才会监听。
编辑选项
BreakPoint Condition
当我们通过Xcode对breakpoint进行编辑时,可以发现normal breakpoint和symbolic breakpoint都有一个”Condition”输入选项,这个的作用很容易理解,只有在设置的condition表达式为YES的情况下这些断点才会起作用。
例如,下图中的breakpoint在判断字符串相等的时候才会停止运行:
可以注意到这里使用stringWithUTF8Stirng:方法,原因在于lldb的expression parser有一个bug,不兼容非ASCII字符,需要处理一下才行,否则会报错“An Objective-C constant string's string initializer is not an array”,参考:http://stackoverflow.com/questions/17192505/error-in-breakpoint-condition
更加简单一些的例子就不说了,比如 i == 99之类的简单比较,只要表达式的结果为BOOL类型即可。
Breakpoint Actions
可以看到上面的每种breakpoint编辑选项中基本上都有“Add Action”选项,当breakpoint被触发时,都首先会执行我们设置的这些action,然后我们才能得到控制权,即Xcode上面才会显示程序停止执行的UI。这个Action通过例子比较好理解,我们通过上面那个setObject:forKey:的异常来说明。代码如下:
设置Breakpoint:
可以看到上图中,我们一共设置了3个action。第一个action,用来打印exception的详细信息,用法参考:http://stackoverflow.com/questions/17238673/xcode-exception-breakpoint-doesnt-print-details-of-the-exception-being-thrown。
第二个action,我们使用shell命令“say”,让电脑发声,把一段文字读出来。
第三个action,我们使用“bt”命令来打印调用栈信息
设置完成之后,当异常发生时,我们会听到电脑发声念上图中的英文,然后在log中可以看到如下信息,第一行是Exception的描述信息,下面是调用堆栈:
Continuing after Evaluation
看一下breakpoint的编辑弹窗,我们可以发现有一个 “Automatically continue after evaluation actions” checkbox选项。当我们勾选这个checkbox之后,debugger会执行breakpoint中添加的所有的actions,然后继续执行程序。对于我们来说,除了触发一大堆command并且执行时间很长的情况之外,程序会很快跳过这个breakpoint,所以我们可能根本不会注意到这个breakpoint的存在。所以,这个选项的功能相当于在执行的最后一个action之后,直接输入continue命令继续执行。
有了这个很强大的功能,我们可以直接通过breakpoints来单独对我们的程序进行修改。在某行代码时停止执行,使用”expression”命令来直接修改程序的某个变量设置直接修改UI,然后继续执行。expression / call 配合这个选项的时候,会非常强大,可以很方便实现很多很强大的功能。
例如,我们实现一个如下的功能,把tableview的第一个cell的selectBackgroundView的背景色改为红色:
action的内容为“expression [[cell selectedBackgroundView] setBackgroundColor:[UIColor redColor]]”,这里的表达式先不用关心,我们后面LLDB章节会讲到,修改之后,当我们点击cell的时候,cell的背景就会如下图一样变红:
使用这种方式,我们在不需要修改一行代码的情况下,只需要通过修改breakpoint,就可以实现对UI的各种调试效果。
iOS开发——测试篇&breakpoints、lldb 和 chisel 的详解的更多相关文章
- iOS开发——开发实战篇&版本控制SVN和Git使用详解
版本控制SVN和Git使用详解 公司的实际开发中,在天朝使用较多的还是SVN,因为SVN是集中式的,在天朝上班你们都懂的! -----------------svn--------- ...
- IOS 开发环境,证书和授权文件等详解
(转自:http://blog.csdn.net/gtncwy/article/details/8617788) 一.成员介绍1. Certification(证书)证书是对电脑开发资格的认证, ...
- 【转】IOS 开发环境,证书和授权文件等详解
(转自:http://blog.csdn.net/gtncwy/article/details/8617788) 一.成员介绍1. Certification(证书)证书是对电脑开发资格的认证, ...
- 【IOS 开发】Object-C 入门 Xcode 环境详解
作者 : 韩曙亮 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/38424965 一. Xcode 环境安装 与 工程创建 1. ...
- 【转】 iOS 开发之静态库.a和动态库详解 -- 不错
原文网址:http://blog.csdn.net/lxl_815520/article/details/52154331 一, 简单介绍 1.什么是库 库是程序代码的集合,是共享程序代码的一种方式 ...
- IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解
copy与retain的区别: copy是创建一个新对象,retain是创建一个指针,引用对象计数加1.Copy属性表示两个对象内容相同,新的对象retain为1 ,与旧有对象的引用计数无关,旧有对象 ...
- 【iOS开发】 AudioSession设置, 切换扬声器和听筒详解-保留其他应用音乐(备忘)
本文转载至 http://blog.sina.com.cn/s/blog_693de6100101f1g8.html (2013-04-10 17:25:24) 转载▼ 标签: audiosessio ...
- iOS开发——加载、滑动翻阅大量图片解决方案详解
加载.滑动翻阅大量图片解决方案详解 今天分享一下私人相册中,读取加载.滑动翻阅大量图片解决方案,我想强调的是,编程思想无关乎平台限制. 我要详细说一下,在缩略图界面点击任意小缩略图后,进入高清 ...
- iOS开发Swift篇—(一)简单介绍
iOS开发Swift篇—简单介绍 一.简介 Swift是苹果于2014年WWDC(苹果开发者大会)发布的全新编程语言 Swift在天朝译为“雨燕”,是它的LOGO 是一只燕子,跟Objective-C ...
随机推荐
- c++builder 代码输入助手
c++builder 代码输入助手 指针箭头.指针符号-> 输入太麻烦 java.c#.delphi 语音,输入. 一个字符,就可以弹出代码提示窗口.很是方便. c++,输入->,需要按3 ...
- 用jmap分析java程序
之前的随笔提到用jstack分析java线程情况,也是在这个项目中,当线程的问题解决之后,发现程序的内存一直增长,于是用jmap工具分析了一下java程序占用内存的情况. 命令很简单,直接 jmap ...
- Ubuntu之系统交换分区Swap增加与优化
http://os.51cto.com/art/201212/372860.htm http://blog.csdn.net/xingyu15/article/details/5570225 ...
- C#.NET 消息机制
一.消息概述 众人周知,window系统是一个消息驱动的系统, windows操作系统本身有自己的消息队列,消息循环,它捕捉键盘,鼠标的动作生成消息,并将这个消息传给应用程序的消息队列. 余下的工作有 ...
- Unable to load dll 的解决方案
前几天在做项目时,需要用到一个非托管的 dll 库,其实使用 .Net 的互操作技术可以很方便地调用非托管 dll 文件中的函数,但是在执行时出现了“Unable to load dll HRESUL ...
- cf754 B. Ilya and tic-tac-toe game
呵呵呵,这个题简直是一直在乱做,真是最近太弱了 #include<bits/stdc++.h> #define lowbit(x) x&(-x) #define LL long l ...
- cocos2dx使用TiledMap创建斜45度地图场景
做游戏,场景是一个很重要的部分,如果缺少这一步,很难做出好的游戏,对于cocos2dx来说,有很多2D的地图编辑器可以用,效果都还可以,其中Tiled是支持的比较好的,它支持Tiled编辑出来的几种模 ...
- Android读取assets目录下的资源
1.获取资源的输入流 资源文件 sample.txt 位于 $PROJECT_HOME/assets/ 目录下,可以在 Activity 中通过 Context.getAssets().open(“s ...
- 关于favicon.ico的使用
http://www.cnblogs.com/LoveJenny/archive/2012/05/22/2512683.html
- 【转】Android -- Looper.prepare()和Looper.loop()
Looper.prepare()和Looper.loop() 原文地址:http://blog.csdn.net/heng615975867/article/details/9194219 Andro ...