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

77

我知道当我设置断点时可以键入print someFloatVariable或者po [self someIvarHoldingAnObject],但我无法像做有用的事情:

[self setAlpha:1];

然后它会输出:

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

奇怪的是,我可以调用po [self someIvarHoldingAnObject]并打印它的描述。

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


在lldb-for-gdb-users.txt中有一个C语言的示例:expr (int) printf("...")。也许你应该在方法调用前加上expr(type)前缀? - osgx
2个回答

128

获取 gdb 与 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”,分别用于设置和获取float类型实例变量。这是一个简单的示例,但它展示了如何使用它。以下是我为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

“<no result>”的修复已经提交到lldb TOT源代码中了。


expr -- [self setAlpha:0.5f] 或 expr -- [self setAlpha:1] 都会使问题中的视图完全从屏幕上消失。看起来好像发生了什么,但绝对不是正确的事情。我只能在设置断点时输入这些命令。或者在代码仍在运行/未暂停时是否有一种方法可以执行此类操作? - Proud Member
不,当你调用这个方法时,需要停止该进程。如果此选择器采用浮点类型,则可能会遇到Xcode 4.5的lldb的一个缺点 - 如果函数参数采用浮点类型并且您没有调试信息,则lldb不会提供任何方法将值作为浮点数传递。它将无条件地将其作为双精度传递,遵循旧的C语言无原型参数提升规则。如果lldb具有此类的调试信息,则应该能够做正确的事情。在未来的版本中,ObjC编程中的许多此类问题都将得到解决。 - Jason Molenda
如果你遇到了浮点数和双精度问题,那么传递给setAlpha的值可能不是你期望的值,而是一些看起来很随机的疯狂数字,可能非常接近0。 - Jason Molenda
如果你调用的函数不是你程序的一部分,你通常需要显式声明它们的返回类型,这样lldb才知道如何调用它们。谢谢!那帮了我大忙了。 - kakyo

10

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

expression

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

// code will execute now

空白行以结束并执行代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接