繁体   English   中英

如何在 LLDB 中打印实际(派生)object 属性

[英]How to print actual(derived) object properties in LLDB

代码示例:

class IA
{
public:
    virtual int getA() = 0;
};

class A:public IA
{
public:
    int getA() override
    {
        return m_a;
    }
private:
    int m_a = 10;
};

void main()
{
    A* a = new A();
    IA* ia = a;
}

在带有set print object on a可以使用ia指针轻松打印 object 内容。

//with print object on
p *ia
$1 = (A) {<IA> = {_vptr$IA = 0xf330c8 <vtable for A+16>}, m_a = 10}

//without print object on
p *ia
$2 = {_vptr$IA = 0xf330c8 <vtable for A+16>}

可以在lldb中做同样的事情吗? 我在官方文档中找不到任何东西。 这就是我在 lldb 中得到的:

p *ia
(IA) $0 = {}
p *a
(A) $1 = (m_a = 10)

lldb 有两种从目标程序访问类型值的方法, expr (别名为p )和frame variable (别名为v )。

expr是一个完整的表达式评估器,它使用 clang 前端和后端来解析和评估您传递给它的表达式,“就好像它在您停止的地方插入到代码中一样”。

frame var是一种 C-ish 伪语言,用于访问变量、寄存器或 memory 区域的元素。

然后,任一方法的结果值通过一个通用系统呈现,首先通过获取结果的“动态类型”(相当于设置“打印对象”),然后将其传递给“数据格式化程序”架构。

处理时:

(lldb) p *ia

当指针作为值从表达式返回到“动态类型”检测阶段时,指针已被取消引用,因此无法判断它真的来自指向 A 的指针。

lldb 选择让expr尽可能地遵循源语言的规则,这会妨碍这里,但这意味着您可以将相当复杂的表达式传递给命令并让它们像在代码中一样工作。

除其他外,它可以执行 C++ 强制转换,因此如果您需要动态类型可用(例如,如果您想调用仅在完整类型中的方法),您可以手动完成:

(lldb) p ((A *)ia)->some_A_method()

gdb 的print使用了一个手工构建的解析器,它从最深的子表达式中评估表达式,因此它可以停止获取每个子表达式的动态类型。 然而,这样做会使成为一个准确的 C++ 解析器的工作变得更加困难。 总是有取舍...

哦,

(lldb) v *ia
(A) *ia = (m_a = 10)

可以获取动态类型,因为v解析器返回 object:“SBValue”代表局部变量ia的“SBValue”的解引用值 - 所以结果知道值来自哪里,并且可以获取所有动态类型方式在印刷阶段。 我们还没有教v进行强制转换或 function 调用 - 主要是为了使其解析器保持简单和可预测。 但除此之外, v通常比变量打印更方便p

当您只是打印局部变量或其子变量时, v也更有效,并且不那么脆弱,因为它只需要实现值的类型并获取其 memory,而不是模拟当前上下文足以满足 clang。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM