IOSiOS学习笔记iOS开发

Xcode 常用 LLDB 指令

2018-05-10  本文已影响166人  CoderHG

LLDBXcode 中自带的一个调试工具,在开发的过程中使用好了这个调试工具,不仅是能力的一种提升,更是一种装逼的 神器

一、如何进入 LLDB

通常当程序 crash 或者有断点的时候,会自动的变成 LLDB 模式。也可以手动 处理,直接点击这里:


image.png

也会变成 LLDB 模式。最终的效果是这样的:


image.png

二、使用 LLDB

2.1 expr 指令

这个指令的意思,能实时的执行代码中的代码逻辑。就像下面这样的:

image.png

当点击下一步执行的时候,NSLog 打印的值是 CoderHG 而不是 Coder。这个功能想想都感觉挺不错的。

由于最近在学习 ShellPython ,于是刚刚这样脑补了一下:

image.png

这样是行不通的,难怪大家都说 ShellPython 很强大。[偷笑5分钟,犯困一小时]

2.2 call

这个指令与 expr 类似,调用一行代码,形如这样的:

call self.view.backgroundColor = [UIColor redColor];

image.png

2.3 打印

其实关于打印,应该所有的小伙伴都知道的。接着上面的步骤,做如下的操作:


image.png

在 LLDB 中有两个常见的打印指令 ppo

image.png

2.4 操作内存

对内存的操作,无非就是读写操作。
修改内存中的值:

memory write 内存地址 数值

如:memory write 0x7ffee685dba8 25

读取内存操作:

memory read/数量 _ 格式 _ 字节数 内存地址

或者

x/数量 _ 格式 _ 字节数 内存地址

2.4.1 格式
2.4.2 字节大小

如:

memory read/1wx 0x7ffee14a5ba8
memory read/1wd 0x7ffee14a5ba8

寓意是:读取 0x7ffee14a5ba8 中 4 个字节的内容。
示例如下:

image.png

2.5 bt

bt 返回所有的调用栈, 形如:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
  * frame #0: 0x000000010758b6fd LLDBDev`-[ViewController viewDidLoad](self=0x00007fedad7057e0, _cmd="viewDidLoad") at ViewController.m:27
  **中间被我干掉了很多。**
    frame #34: 0x000000010758b79f LLDBDev`main(argc=1, argv=0x00007ffee8674108) at main.m:14
    frame #35: 0x000000010c2d1d81 libdyld.dylib`start + 1
    frame #36: 0x000000010c2d1d81 libdyld.dylib`start + 1

这个指令很强大,现在的 Xcode 在这里都显示不全了:


image.png

所以只能借助 bt 指令。

三、实战

没有实战的纸上谈兵,都是耍流氓。
在开始之前,先定义一个 Class,代码如下所示:

#import <Foundation/Foundation.h>

@interface HGObject : NSObject

/** 年龄 */
@property (nonatomic, assign) NSInteger age;
/** 身高 */
@property (nonatomic, assign) NSInteger height;

@end



#import "HGObject.h"

@implementation HGObject

@end

很简单的一个Class。

3.1 查看一个对象的 isa 指针

大家都说一个instance 对象中的 isa 的值就是当前 instance 对象的 class 对象的值,接下来求证一下。先写一段简单的代码:

Class cls = NSClassFromString(@"HGObject");
id obj = [[cls alloc] init];
NSLog(@"%@, %@", cls, obj);
image.png

运行代码发现:

看不到任何的地址显示,所以只能是借助 LLDB 调试工具,这里既是是使用简单的 p 或者 po指令都是不可以的。需要借助上面说的 操作内存 的指令。

image.png

轻松搞定,上图中是不是就说明了一个 Class 对象的 instance 对象的 isa 的值就是其 class 对象本身的值呢?是的,本来就是这样的。

3.2 对象中的地址查看

简单的实现如下代码:

HGObject* obj = [[HGObject alloc] init];
obj.age = 18;
obj.height = 2;

NSLog(@"%@", obj);

在 NSLog 处打一个断点,运行代码,打开内存查看视图:


image.png

刚打开是这样的:


image.png

将 obj 的地址写入,再看下面这张图:


image.png

看到上面的内存图,发现一个规律,请看下图:


image.png

上图中的内存分布,如红框框所示,分别是 isa,_age 与 _height。为了验证其正确性,可以修改一下其中的值,看一下效果:


image.png

上图中的逻辑大概为:查找 _age 与 _height 对应的地址,然后修改其地址的值,然后刷新看内存视图。

四、说在最后的话

记录这些技巧,一方面是因为这些技巧往往都被我们所忽视,记录一下说明自己了解过。但是一旦熟练使用这些技巧,往往在开发中能减少大量的调试时间。

其实,为了装逼才是最重要的。

上一篇 下一篇

猜你喜欢

热点阅读