我有一个自定义类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元素?
非常感谢您的帮助。
诉P>
编辑:回复评论
我正在使用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
}
}
答案 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代码中进行计算而不是仔细阅读表达式求值程序。
生成的格式化程序将更快,可能更可靠 - 并且它将适用于所有情况。