lldb:向量元素的自定义摘要(c ++)

时间:2014-09-04 12:42:14

标签: c++ xcode lldb

我有一个自定义类MyNameSpace::String,我在lldb中创建了一个摘要。例如,对于MyNameSpace::String myString="a string",这是lldb中的摘要:

frame variable myString
   (MyNameSpace::String) myString = "a string"

如何获得std::vector<MyNameSpace::String>vecString的摘要,该摘要看起来是std::vector<std::string>vec的摘要?

到目前为止,以下是关于不同变量的命令frame variable的结果:

  • 标准字符串

    的向量
    frame variable vec
    (std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >) vec = size=3 {
    [0] = "bonjour"
    [1] = "je suis"
    [2] = "vincent"
    }
    
  • 我的自定义字符串

    的向量
    frame variable vecString
    (std::__1::vector< MyNameSpace::String, std::__1::allocator< MyNameSpace::String> >) vecString = size=2 {
      [0] = {
        value = 7453010373645639777
      }
      [1] = {
        value = 18302628889929726940
      }
    }
    

如何将我的自定义摘要应用于我的vector元素?

非常感谢您的帮助。

编辑:回复评论

我正在使用lldb-310.2.37。

我使用脚本为我的String类创建了摘要:

def generic_summary(valueObject,dict):
    name=valueObject.GetName()
    return valueObject.GetFrame().EvaluateExpression(name+".toString().toStdString()").GetSummary()

debugger.HandleCommand('type summary add MyNameSpace::String -F CustomSummaries.generic_summary')

与〜/ .lldbinit中的正确命令一致。

frame variable -T vecString

(lldb) frame variable -T vecString
(std::__1::vector<MyNameSpace::String, std::__1::allocator< MyNameSpace::String> >) vecString = size=2 {
  (MyNameSpace::String) [0] = {
    (MyNameSpace::uint8) value = 7453010373645639777
  }
  (MyNameSpace::String) [1] = {
    (MyNameSpace::uint8) value = 18302628889929726844
  }
}

1 个答案:

答案 0 :(得分:3)

所以,正如你意识到 - 正确 - 你的问题就在这里:

name=valueObject.GetName()

你问题的真正答案是&#34;不做你正在做的事情&#34;。让我们一步一步来。

您在这里询问其名称的值。如果我有

struct Foo { int x; int y; } aFoo;

&#34; x&#34;的SBValue的名称将是&#34; x&#34;。如果你想要&#34; aFoo.x&#34;,你想要的是表达式路径,顾名思义就是你要在表达式中输入的内容来引用那个价值。

当合成儿童出现时,事情会变得棘手。

您可能认为您的元素[0]具有vecString [0]的表达式路径。但它没有赢。它很可能只是[0]。为什么呢?

这与合成儿童的创作方式有关。具体来说,虽然&#34; x&#34; in&#34; aFoo&#34;知道它的父对象是&#34; aFoo&#34; struct,vecString的[0]元素没有。它是从整块布料创建的,其位置是某个内存地址。 给定libc ++向量的布局:

struct vector<T> { T* begin; T* end; T* endStorage; };

公式为locationOfXElement = begin + X * sizeof(T)

(这是勾勒出来的伪代码,但是应对我!)

LLDB做的是,计算该位置,然后说 - 好吧,现在在内存中的该位置创建一个ValueObject(SBValue的内部术语,如果您愿意)。这与底层向量没有任何关系。它只是某个地方的价值。因此,表达路径的概念是错误的。

&#34;但你可以解决这个问题!&#34;,你宣布。

是的,我们可能会。它会采用合成子项具有逻辑父项的概念,以及模拟对结构的访问类型的概念:它是否类似数组?类似指针?结构类? 这样就可以编写myObject [N],而不是myObject-&gt; foo和myObject.bar

这样就可以了。但它仍然无法解决您的问题。

现在考虑

而不是矢量
std::map<yourString,int> myMap;

LLDB将此视为一套美化的

pair<myString,int> { myString key; int value };

命名为[0],[1],......

让我们说表达路径语法正确,我们将其表示为

myMap[0].key

尝试在表达式中使用它!是的 - 你猜对了 - 它会失败! myMap :: operator []需要一个字符串,而不是数字索引。 在这种情况下,无论表达路径多么聪明,LLDB选择的演示模式都会破坏合成儿童在代码中的可用性。

我确信这也可以修复,但在一天结束时,有充分的理由在评估表达式时不使用合成子代。请考虑以下事项:

vecString[0].size()

你想让operator []访问你的vector元素吗?或者您想要使用合成儿童吗?

那怎么样?

vecString[0] = "hello"

现在?

vecString[0] = vecString[0] + " world!"

一般来说,混合合成儿童和表达的问题很棘手,我们选择了#34; no no&#34; - 合成儿童对表达评估者完全透明。

现在我们回到&#34;不做你正在做的事情&#34;,不要尝试在格式化程序中运行代码,除非你真的真的真的真的需要,甚至为这样的头痛做好准备。

我将假设&#34; toString()。toStdString()&#34;本质上是做一些内存访问和一些计算 - 你想要做的是使用内存读取操作在Python代码中复制它,并在Python代码中进行计算而不是仔细阅读表达式求值程序。

生成的格式化程序将更快,可能更可靠 - 并且它将适用于所有情况。