原创Blog,转载请注明出处
http://blog.csdn.net/hello_hwc?viewmode=list
我的stackoverflow

前言:LLDB是个开源的调试器,与XCode绑定的

LLDB的使用中,Swift与Objective C还是有一些差别的

本文主要侧重LLDB的常用命令

资料(目前状态XCode 7.2 Swift 2.1.1),非XCode 7.2+本文代码可能不能运行

  • objc.io(强烈建议有Objective C经验,但是对LLDB不熟悉的深入研究下)
  • Apple官方文档
  • LLDB的文档
  • 一个封装LLDB的库,可以辅助调试
  • 2015 WWDC视频

对了,Swift到现在也不过一岁半,所以LLDB对于Swift的支持肯定不如OC那么好。

如何打开LLDB如何使用?

通常的方式就是断点,另外,关于利用XCode图形化调试,在我这篇文章里有详细讲解

本文适合XCode 7.2 +
不管是在程序中加断点

还是手动的暂停程序

让代码停在Swift Error 或者Objective C异常

停在Objective C异常

(lldb) br s -E  objc
Breakpoint 6: where = libobjc.A.dylib`objc_exception_throw,address = 0x000000010dededbb

停在Swift Error

(lldb) br s -E swift
Breakpoint 7: where = libswiftCore.dylib`swift_willThrow,address = 0x000000010e55ccc0

停在某一种类型的Swift Error

(lldb) br s -E swift -O EnumError
Breakpoint 8: where = libswiftCore.dylib`swift_willThrow,address = 0x000000010e55ccc0

以此作为开端,希望读者能耐心看完,本文很长

准备工作

为了方便,我们先写好这样的一个Model类,定义个ErrorType,并且定义个实例方法抛出异常

enum CustomError:ErrorType{
    case LeoError1
    case LeoError2
}
class Person:NSObject{
    var name:String
    var age:UInt32
    init(name:String,age:UInt32){
        self.name = name
        self.age = age
    }
    //重写description是为了方便调试
    override var description:String{
        return "name:\(name) age:\(age)"
    }
    func PersonException() throws{
        throw CustomError.LeoError1
    }
}

然后在viewDidLoad中初始化一个对象,并打一个断点

let person = Person(name: "Leo",age: 23)

打印命令 p/po

p

(lldb) p person
(SwiftLLDBDemo.Person) $R0 = 0x00007f99b8d30b40 {
  ObjectiveC.NSObject = {
    isa = SwiftLLDBDemo.Person
  }
  name = "Leo"
  age = 23
}

po

(lldb) po person
name:Leo age:23

p命令会打印出对象的类型,如果是Objective C对象,会打印出isa,以及属性的值
po 命令 对于继承自NSObject得对象,指示会打印出description中的内容

再举个例子

(lldb) po ["123","345"]
▿ 2 elements
  - [0] : "123"
  - [1] : "345"

(lldb) p ["123","345"]
([String]) $R2 = 2 values {
  [0] = "123"
  [1] = "345"
}

也可以,调用一段代码

(lldb) p for i in 1...3{ print(i) }
1
2
3

执行代码 e

expression命令可以帮助我们执行代码,

(lldb) e person.name = "Jack"
(lldb) p person
(SwiftLLDBDemo.Person) $R1 = 0x00007f9bf1424c20 {
  ObjectiveC.NSObject = {
    isa = SwiftLLDBDemo.Person
  }
  name = "Jack"
  age = 23
}

在这我们深入的研究所有命令

(lldb) help

内容太多,不拷贝进来了,自己在XCode里敲敲试试吧。

可以看到,有一部分是alias部分,有linux经验的同学应该知道,alias就是将一个简单的命令设置为复杂命令的别名。我们上面讲到的两个命令p/po就是两个alias命令

p         -- ('expression --')  Evaluate an expression (ObjC++ or Swift) in
               the current program context,using user defined variables and
               variables currently in scope.
  po        -- ('expression -O -- ')  Evaluate an expression (ObjC++ or Swift)
               in the current program context,using user defined variables and
               variables currently in scope.

所以,p命令,本质是expression -- ;po命令,本质是expression -O --

(lldb) expression -- person
(SwiftLLDBDemo.Person) $R0 = 0x00007f96a3f792d0 {
  ObjectiveC.NSObject = {
    isa = SwiftLLDBDemo.Person
  }
  name = "Leo"
  age = 23
}
(lldb) expression -O -- person
name:Leo age:23

更加复杂的执行

例如,动态的修改view的背景色

e self.view.backgroundColor = UIColor.blueColor

Expression命令很灵活

格式化打印 -f (format)

(lldb) expr -f bin -- person.age 
(UInt32) $R2 = 0b00000000000000000000000000010111
(lldb) expr -f oct -- person.age
(UInt32) $R3 = 027
(lldb) expr -f hex -- person.age
(UInt32) $R4 = 0x00000017

格式化打印可以更简单

(lldb) p/x person.age
(UInt32) $R5 = 0x00000017

打印Raw value expr -R -- 变量

(lldb) expr -R -- person
(SwiftLLDBDemo.Person) $R6 = 0x00007f96a3f792d0 { ObjectiveC.NSObject = {}
  name = { _core = { _baseAddress = { _rawValue = 0x0000000101041298 "Leo" }
      _countAndFlags = { value = 3 }
      _owner = None { Some = { instance_type = 0x0000000000000000 }
      }
    }
  }
  age = { value = 23 }
}

显示变量类型expr -T -- 变量

(lldb) expr -T -- person
(SwiftLLDBDemo.Person) $R7 = 0x00007f96a3f792d0 {
  (NSObject) ObjectiveC.NSObject = {
    (Class) isa = SwiftLLDBDemo.Person
  }
  (String) name = "Leo"
  (UInt32) age = 23
}

当然也可以结合多个使用expr -RRT -- person

帮助命令,可以再深入看看其他执行选项,不过不是很常用

help expression

LLDB变量

LLDB的变量和脚本语言类似,以美元符号开头,使用的时候也要带着美元符号,调用的时候和Swift的语法一致
例如

(lldb) e var $a = 10
(lldb) p $a
(Int) $a = 10

(lldb) e var $b = Person(name: "Jack",age: 25)
(lldb) p $b
(SWTest.Person) $b = 0x00007f8909539080 {
  ObjectiveC.NSObject = {
    isa = SWTest.Person
  }
  name = "Jack"
  age = 25
}

断点

断点采用这个命令breakpoint,缩写br
断点命令的文档较少,这里先列出文档

(lldb) help breakpoint
The following subcommands are supported:

      clear   -- Clears a breakpoint or set of breakpoints in the executable.
      command -- A set of commands for adding,removing and examining bits of
                 code to be executed when the breakpoint is hit (breakpoint
                 'commands').
      delete -- Delete the specified breakpoint(s). If no breakpoints are specified,delete them all. disable -- disable the specified breakpoint(s) without removing them. If none are specified,disable all breakpoints. enable -- Enable the specified disabled breakpoint(s). If no breakpoints are specified,enable all of them. list -- List some or all breakpoints at configurable levels of detail. modify -- Modify the options on a breakpoint or set of breakpoints in the executable. If no breakpoint is specified,acts on the last created breakpoint. With the exception of -e,-d and -i,passing an empty argument clears the modification. name -- A set of commands to manage name tags for breakpoints set -- Sets a breakpoint or set of breakpoints in the executable.

breakpoint set -E language
breakpoint s -E swift -O ErrorType

列出断点

(lldb) br li
Current breakpoints:
1: file = '/Users/huangwenchen/Desktop/SWTest/SWTest/ViewController.swift',line = 27,locations = 1,resolved = 1,hit count = 1

  1.1: where = SWTest`SWTest.ViewController.viewDidLoad (SWTest.ViewController)() -> () + 75 at ViewController.swift:27,address = 0x000000010ef8556b,resolved,hit count = 1

禁用断点

(lldb) br dis 1
1 breakpoints disabled.

删除断点

(lldb) br del 1
1 breakpoints deleted; 0 breakpoint locations disabled.
(lldb) br li
No breakpoints currently set.

添加断点

(lldb) br set -f ViewController.swift -l 28
Breakpoint 2: where = SWTest`SWTest.ViewController.viewDidLoad (SWTest.ViewController)() -> () + 139 at ViewController.swift:29,address = 0x000000010ef855ab

也可以简写为

(lldb) b ViewController.swift:28
Breakpoint 3: where = SWTest`SWTest.ViewController.viewDidLoad (SWTest.ViewController)() -> () + 139 at ViewController.swift:29,address = 0x000000010ef855ab
(lldb) br li
Current breakpoints:
2: file = 'ViewController.swift',line = 28,hit count = 0
  2.1: where = SWTest`SWTest.ViewController.viewDidLoad (SWTest.ViewController)() -> () + 139 at ViewController.swift:29,address = 0x000000010ef855ab,hit count = 0 

3: file = 'ViewController.swift',hit count = 0
  3.1: where = SWTest`SWTest.ViewController.viewDidLoad (SWTest.ViewController)() -> () + 139 at ViewController.swift:29,hit count = 0

断点Name

断点名称是用来管理一组断点的,通过name可以启用或者禁用一组断点,一个断点可以有多个name,很像tag。

br set -f ViewController.swift -l 28 -N leo
(lldb) br set -f ViewController.swift -l 28 -N leo
Breakpoint 2: 3 locations.
(lldb) br li
Current breakpoints:
1: file = '/Users/huangwenchen/Desktop/SWTest/SWTest/ViewController.swift',line = 34,hit count = 1

  1.1: where = SWTest`SWTest.ViewController.viewDidLoad (SWTest.ViewController)() -> () + 75 at ViewController.swift:34,address = 0x00000001070d51fb,hit count = 1 

2: file = 'ViewController.swift',locations = 3,resolved = 3,hit count = 0
  Names:
    leo

  2.1: where = SWTest`SWTest.ViewController.__deallocating_deinit + 12 at ViewController.swift,address = 0x00000001070d538c,hit count = 0 
  2.2: where = SWTest`SWTest.ViewController.init (SWTest.ViewController.Type)(nibName : Swift.Optional<Swift.String>,bundle : Swift.Optional<__ObjC.NSBundle>) -> SWTest.ViewController + 57 at ViewController.swift,address = 0x00000001070d53f9,hit count = 0 
  2.3: where = SWTest`SWTest.ViewController.init (SWTest.ViewController.Type)(coder : __ObjC.NSCoder) -> Swift.Optional<SWTest.ViewController> + 16 at ViewController.swift,address = 0x00000001070d56d0,hit count = 0

在加上名字以后,我们就可以通过名字来操作断点了

(lldb) br disable -N leo
1 breakpoints disabled.

在某一个函数上加断点

例如,在准备Person的函数中personLoop添加断点

(lldb) br s -F personLoop
Breakpoint 2: 2 locations.
(lldb) br li
Current breakpoints:
1: file = '/Users/huangwenchen/Desktop/SWTest/SWTest/ViewController.swift',line = 40,hit count = 1

  1.1: where = SWTest`SWTest.ViewController.viewDidLoad (SWTest.ViewController)() -> () + 75 at ViewController.swift:40,address = 0x000000010f6d51bb,hit count = 1 

2: name = 'personLoop',locations = 2,resolved = 2,hit count = 0
  2.1: where = SWTest`SWTest.Person.personLoop (SWTest.Person)() -> () + 12 at ViewController.swift:25,address = 0x000000010f6d45cc,hit count = 0 
  2.2: where = SWTest`@objc SWTest.Person.personLoop (SWTest.Person)() -> () + 4 at ViewController.swift,address = 0x000000010f6d4664,hit count = 0

条件断点

先在这里加一个断点

当某种条件产生的时候触发的断点,例如停在1000次循环的第800次

然后添加条件,停在i == 80

(lldb) br li
Current breakpoints:
1: file = '/Users/huangwenchen/Desktop/SWTest/SWTest/ViewController.swift',address = 0x00000001094d81bb,hit count = 1 

2: file = '/Users/huangwenchen/Desktop/SWTest/SWTest/ViewController.swift',hit count = 1

  2.1: where = SWTest`SWTest.Person.personLoop (SWTest.Person)() -> () + 111 at ViewController.swift:27,address = 0x00000001094d762f,hit count = 1 

(lldb) br modify -c 'i == 80'
(lldb) po i
80

断点行为

当断点触发的时候,执行的LLDB代码

例如,当i==80的时候,输出sum

(lldb) br li
Current breakpoints:
1: file = '/Users/huangwenchen/Desktop/SWTest/SWTest/ViewController.swift',line = 40,hit count = 1

  1.1: where = SWTest`SWTest.ViewController.viewDidLoad (SWTest.ViewController)() -> () + 75 at ViewController.swift:40,address = 0x00000001057391bb,hit count = 1 

3: file = '/Users/huangwenchen/Desktop/SWTest/SWTest/ViewController.swift',line = 27,hit count = 0

  3.1: where = SWTest`SWTest.Person.personLoop (SWTest.Person)() -> () + 111 at ViewController.swift:27,address = 0x000000010573862f,hit count = 0 

(lldb) br modify -c 'i == 80' 3
(lldb) br command add 3
Enter your debugger command(s). Type 'DONE' to end.
> po sum
> DONE
 po sum
3160

其他断点相关

lldb中输入

(lldb) help br set

篇幅限制,不列出help的结果了

类型查找Type

抛出一个异常,不知道是啥的时候怎么办?

(lldb) type lookup CustomError
enum CustomError : ErrorType {
  case LeoError1
  case LeoError2
  var hashValue: Swift.Int {
    get {}
  }
  var _code: Swift.Int {
    get {}
  }
}

可以简写

(lldb) ty l CustomError
enum CustomError : ErrorType {
  case LeoError1
  case LeoError2
  var hashValue: Swift.Int {
    get {}
  }
  var _code: Swift.Int {
    get {}
  }
}

LLDB中的异常处理

执行一个抛出异常的方法

(lldb) e person.personException()
(SWTest.CustomError) $E0 = LeoError1

流程控制

frame info 查看当前所在的位置

(lldb) frame info
frame #0: 0x000000010573862f SWTest`SWTest.Person.personLoop (self=0x00007fbaf1d054d0)() -> () + 111 at ViewController.swift:27
  • c 继续运行
  • n next 下一行
  • s step in
  • finish step out

函数提前返回

thread return

通过这个命令,可以很好的隔离函数,通常用在函数的最开始位置,避免ARC引用计数问题

最后

欢饮关注我的CSDN博客,很长一段时间内,我会持续的更新iOS/Swift/Objective C相关的文章

LLDB调试的文章应该还有一篇进阶使用的,近期会更新

Swift 代码调试核武-LLDB调试基础的更多相关文章

  1. iOS:调试无法在XCode中运行

    我正在使用XCode4和iOSSDK4.3.我的调试工作正常,但现在我发现在设置断点时,应用暂停,但XCode不关注编辑器中的行.点击断点时也不会显示绿色箭头.我有一个在AppDelegate中分配的UINavigationController.当我在didFinishLaunchingWithOptions中设置断点时,一切都按预期工作:这是当一个断点暂停了mapViewController中的

  2. ios – 异常断点处于活动状态时,应用程序在启动时崩溃

    我刚开始继续开发一款适用于商店的传统iPad应用程序.我注意到项目中的异常断点未启用.当我启用它时,应用程序在启动时崩溃,但在输出窗口中没有给出任何信息,而在线程视图中只有相当无用的信息(见下文)我试着解决它..>将Autolayout设置为关闭.>通过编辑和重新保存故事板文件..但到目前为止没有运气.我的猜测是,故事板中的某些内容被破坏了,因为AppDelegates“确实完成了启动……”

  3. xcode – 如何通过LLDB命令行添加断点操作?

    如果你从Xcode编辑一个断点,有一个超级有用的选项,可以添加一个“Action”,以便在每次遇到断点时自动执行.如何从LLDB命令行添加此类操作?

  4. xcode – 如何在LLDB断点条件下使用堆栈内容?

    问题:我有一种情况,我们在发布期间有媒体播放,并且objc_exception_throw()在此期间大约有5次点击,但总是被捕获,并且它在媒体播放器对象的南边.我厌倦了(a)必须手动连续n次,或者(b)在播放完成之前必须禁用断点.我尝试过的:>使断点忽略前五次命中(问题:它并不总是正好五次)>使用我的目标作为模块创建我自己的符号断点(问题:没有改变)我想做什么:想到的一个解决方案是在断点命中时评

  5. Xcode 4.3.1:在以下情况下不显示代码行:由于未捕获的异常而终止应用程序

    在Xcode的早期版本中,当我遇到崩溃时,Xcode通常会打开发生崩溃的文件,并经常将我带到崩溃的行.最新的Xcode似乎没有做那些让调试变得更难的东西.我是否需要启用一些新设置?

  6. ios – XCode断点应该只挂起当前线程

    我需要调试多线程错误.因此,为了获得生成崩溃的条件,我需要在代码中的特定点停止一个线程,并等待另一个线程到达第二个断点.我现在遇到的问题是,如果一个线程遇到断点,则所有其他线程都被挂起.有没有办法只停止一个线程,让其他线程运行,直到它们到达第二个断点?)其他更有趣的选择:当你点击第一个断点时,你可以进入控制台并写入这应该在该断点处暂停当前上下文中的线程一小时.然后在Xcode中恢复执行.

  7. ios – Veracode,调试符号和XCode

    我正在尝试通过Veracode扫描iOS应用程序:一个应用程序安全平台.为了使它们扫描.IPA,.IPA需要包含调试符号.对于正在使用的Archive构建配置和项目/目标,我已指定:>生成调试符号:是>复制期间剥离调试符号:NO>死代码剥离:没有>默认隐藏的符号:NO>剥离链接产品:没有然而,在提交.IPA时,Veracode仍然给我以下错误:没有调试符号编译的主文件–1个文件我需要采取另一个步骤来创建调试符号,或许是存档吗?

  8. 在Xcode中的选择器上添加符号断点

    我的应用程序中有一个错误,显示以下(部分)堆栈跟踪:为了调试这个,我决定在–[EventboolValue]上添加一个符号断点,推断当发送该选择器时,调试器将停止.然而,没有任何反应.设置断点后,应用程序只是士兵并生成相同的异常而不停止.我已经定义了断点如下:我正在使用LLDB调试器和Xcode4.2解决方法在选择器上设置断点会导致lldb在执行该选择器时停止,而不是在发送时停止.在你的情况下,没

  9. ios – 如何在Xcode 6中的异常断点上打印异常?

    我的应用程序正在崩溃,它似乎陷入了异常断点(这是有道理的),但我无法找到崩溃的原因.这是我尝试过的:>po$eax>po$rax>po$r0>po*(id*)($esp4)对于上述所有尝试,我收到以下错误:错误:使用未声明的标识符’$‘错误:解析表达式时出错1次我也找到了这个LLDBCommandGuide,但没有找到任何有用的东西(有点令人困惑,你不知道你在寻找什么)

  10. 从VS调试iOS时,程序’Mono’已从代码0(0x0)退出

    我有一个问题,当我尝试使用VS2013调试我的iOS应用程序时,我收到以下错误:Theprogram‘Mono’hasexitedwithcode0.我知道以下answer.清理解决方案确实解决了问题,但是下次调试时我需要再次执行…如果有人有长期解决方案,我们将非常感激.解决方法在发射期间它会崩溃吗?

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部