使LLDB将地址重新解释为指向模板实例化类型对象的指针

Make LLDB reinterpret address as pointer to an object whose type is a template instantiation

本文关键字:实例化 类型 指针 对象 地址 LLDB 新解释 解释      更新时间:2023-10-16

在调试时,我在内存中有一个地址,并且知道驻留在该地址上的对象的类型,并且我希望调试器显示该对象的实例。对于不是模板的类型,可以通过print命令来完成,但对于模板实例化的类型,似乎会失败。

请看下面的示例代码:

template<typename T>
class X
{
public:
    X() {
        printf("an");
    }
};
class Y
{
public:
    Y() {
        printf("an");
    }
};

int main(void)
{
    X<int> x;
    Y y;
    return 1;
}

当我运行程序,中断main并尝试将随机有效地址解释为指向X和Y对象的指针时,前者失败了:

(lldb) p *(Y*)0x0000000100000ee6
(Y) $0 = {}
(lldb) p *(X<int>*)0x0000000100000ee6
warning: could not load any Objective-C class information. This will significantly reduce the quality of type information available.
error: use of undeclared identifier 'X'
error: expected '(' for function-style cast or type construction
error: expected expression

是否有任何方法如何在lldb中做到这一点?(编辑:Mac OS X lldb-360.1.65和lldb-310.2.37)

c++的调试信息目前并不抽象地表示模板,它只讨论程序中存在的特定模板实例化。但是lldb的表达式命令使用一个真正的c++解析器(clang),当解析像您尝试的表达式时,它希望首先将X视为抽象模板。因为我们不知道它们,所以我们不能满足clang对X的类型请求,这就是为什么你看到的错误是"未声明的标识符X"。

可以通过为要以这种方式强制转换的指针类型创建一个typedef来解决这个问题。这不是很令人满意,因为你必须提前完成它,而且你必须在代码中的某个地方使用类型定义,因为—为了保持调试信息的大小可管理—clang不会为不使用的类型发出调试信息。但它确实有效,例如,我在示例代码中添加:

typedef X<int> * x_int_ptr;

,然后在main:

  x_int_ptr bar = (x_int_ptr) &x;

以确保它被记录,然后在ldb中我可以这样做:

(lldb) expr *((x_int_ptr) 0x00007fff5fbff798)
(X<int>) $1 = {}