如何在 LLDB 调试器中调用方法或执行代码?

Posted

技术标签:

【中文标题】如何在 LLDB 调试器中调用方法或执行代码?【英文标题】:How to call methods or execute code in LLDB debugger? 【发布时间】:2012-10-01 12:48:19 【问题描述】:

我知道我可以在设置断点或po [self someIvarHoldingAnObject] 时输入print someFloatVariable,但我不能做一些有用的事情,例如:

[self setAlpha:1];

然后吐出来:

错误:'[self' 不是有效命令。

奇怪的是我可以打电话给po [self someIvarHoldingAnObject],它会打印出它的描述。

我相信我在一年前看过一个视频,其中有人演示了如何在运行时通过控制台执行代码,如果我没记错的话,这个人还提供了参数并将对象分配给指针。该怎么做?

【问题讨论】:

有一个例子in lldb-for-gdb-users.txt为C:expr (int) printf ("...")。也许你应该在你的方法调用前加上expr (type) 【参考方案1】:

gdb v.lldb 命令的规范参考是http://lldb.llvm.org/lldb-gdb.html

您想使用计算表达式的 expr 命令。它是除了参数之外还接受“原始输入”的 lldb 命令之一,因此您通常需要一个“--”来指示参数(到 expr)的结束位置和命令的开始位置。例如

(lldb) expr -- [self setAlpha:1]

有一个快捷方式“p”,它为您执行 -- (但不允许任何参数),例如

(lldb) p [self setAlpha:1]

如果您调用的函数不是程序的一部分,您通常需要显式声明它们的返回类型,以便 lldb 知道如何调用它们。例如

(lldb) p printf("hi\n")
error: 'printf' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression
(lldb) p (int)printf("hi\n")
(int) $0 = 3
hi
(lldb)

顺便说一句,有一种巧妙的方法可以解决浮点参数问题。您创建一个“表达式前缀”文件,该文件将添加到您在 lldb 中输入的每个表达式中,并带有您的类方法的原型。例如,我有一个继承自 NSObject 的 MyClass 类,它有两个感兴趣的方法,“setArg:”和“getArg”,它们设置和获取一个浮点 ivar。这是一个愚蠢的小例子,但它展示了如何使用它。这是我为 lldb 编写的前缀文件:

@interface NSObject
@end
@interface MyClass : NSObject
- init;
- setArg: (float)arg;
- (float) getArg;
@end

extern "C" 
  int strcmp (const char *, const char *);
  int printf(const char * __restrict, ...);
  void puts (const char *);

在我的~/.lldbinit 文件中添加

settings set target.expr-prefix /Users/jason/lldb-prefix.h

现在我可以了

(lldb)    p [var getArg]
(float) $0 = 0.5
(lldb)    p [var setArg:0.7]
(id) $1 = 0x0000000100104740
(lldb)    p [var getArg]
(float) $2 = 0.7

您会注意到我在这里也包含了几个标准 C 库函数。完成此操作后,我不再需要转换这些返回类型,例如

(lldb) p printf("HI\n")
<no result>
HI
(lldb) p strcmp ("HI", "THERE")
(int) $3 = -12

(针对“”问题的修复已经提交给 lldb TOT 源。)

【讨论】:

expr -- [self setAlpha:0.5f] 或 expr -- [self setAlpha:1] 都使有问题的视图从屏幕上完全消失。似乎正在发生一些事情,但绝对不是正确的事情。我只能在设置断点时键入这些命令。或者有没有办法在代码仍在运行/未暂停时做这样的事情? 不行,你需要在调用这个方法的时候停止进程。如果此选择器采用浮点类型,则 Xcode 4.5 的 lldb 可能会遇到一个缺点——如果函数参数采用浮点类型并且您没有调试信息,则 lldb 不会为您提供任何方法将值作为浮点数传递。它将按照旧的 C 语言无原型参数提升规则无条件地将其作为双精度传递。如果 lldb 有这个类的调试信息,它应该能够做正确的事情。 ObjC 编程中出现此问题的许多实例将在以后的版本中修复。 注意:如果你遇到了我所说的 float v. double 的问题,你传递给 setAlpha 的值将不是你所期望的,它将是一些看起来很随机的疯狂数字例如,可能非常接近于 0。 “如果您调用的函数不是程序的一部分,您通常需要显式声明它们的返回类型,以便 lldb 知道如何调用它们”。谢谢!这救了我。【参考方案2】:

如果需要多行,请使用expression:

expression

do 
  try thing.save()
 catch 
  print(error)


// code will execute now

空白行结束并执行代码。

【讨论】:

以上是关于如何在 LLDB 调试器中调用方法或执行代码?的主要内容,如果未能解决你的问题,请参考以下文章

在lldb调试中调用c++函数 - 如何使用QuartzCore里面的日志消息

LLDB 数据格式化程序可以调用方法吗?

多个命令为一个的 LLDB 别名

如何查看xcode调用堆栈

在 LLDB 中获取有关坏内存地址的信息

android studio2.3.3 模拟器 Jni函数调用C++对象,lldb调试this指针和相关变量显示无效的原因