如何使用lldb访问map<std::string,int>元素?



使用clang++ -std=c++17 -g source.cpp编译代码段

#include <map>
#include <string>
int main()
{
std::map<std::string, int> m;
m["foo"] = 23;
}

尝试使用密钥foo访问元素,但出现错误:

* thread #1, queue = 'com.apple.main-thread', stop reason = step over
frame #0: 0x000000010000131e a.out`main at source.cpp:8:3
5    {
6      std::map<std::string, int> m;
7      m["foo"] = 23;
-> 8    }
Target 0: (a.out) stopped.
(lldb) p m["foo"]
error: no viable overloaded operator[] for type 'std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int> > >'
candidate function not viable: no known conversion from 'const char [4]' to 'const std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int> > >::key_type' (aka 'const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >') for 1st argument
candidate function not viable: no known conversion from 'const char [4]' to 'std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, int> > >::key_type' (aka 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >') for 1st argument
(lldb) p m[std::string("foo")]
error: no member named 'string' in namespace 'std'
(lldb) p m[std::__1::string("foo")]
error: no matching conversion for functional-style cast from 'const char [4]' to 'std::__1::string' (aka 'std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >')
candidate constructor not viable: no known conversion from 'const char [4]' to 'const std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::allocator_type' (aka 'const std::__1::allocator<char>') for 1st argument
...
candidate constructor not viable: no known conversion from 'const char [4]' to 'std::initializer_list<char>' for 1st argument
candidate constructor not viable: requires 0 arguments, but 1 was provided
...
candidate constructor not viable: requires 4 arguments, but 1 was provided

如何使用lldb以正确的方式处理字符串变量?

您没有说明clang++&您正在使用的lldb。使用Xcode 13附带的工具,我看到:

(lldb) expr m["foo"]
(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >::mapped_type) $0 = 23
(lldb) expr m[std::string("foo")]
(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >::mapped_type) $1 = 23

这显然不是你得到的。这些看似简单的C++表达式实际上最终在幕后创建了一堆模板化实体,而仅从调试信息中重建实例化模板所需的信息是很棘手的,甚至是不可能的。

但是最近在lldb方面做了很多工作来支持为C++标准库构建clang模块,我们可以从中提取必要的信息。要么你有一个旧的lldb没有这个功能,要么由于某种原因,构建clang模块失败了。如果您使用的是当前的lldb,那么您可能需要使用http://bugs.llvm.org看看是否有人能帮你找出问题所在。

同样需要注意的是,lldb并不单独依赖于表达式求值来表示常见的C++(或ObjC/Swift(容器。它还具有一个系统;数据格式化器";它们理解这些容器类的底层结构,并且可以表示不需要调用实际语言访问器的内容。默认情况下,表达式的结果使用数据格式化程序进行格式化(expr --raw --关闭格式化程序(。这就是你看到的原因:

(lldb) expr m
(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >) $0 = size=1 {
[0] = (first = "foo", second = 23)
}

而不是std::map的所有实际字段。

在这种情况下,std::map的数据格式化程序将映射表示为成对的向量。由于钥匙可以是任何东西,这提供了一种更方便的方式来访问元素。。。

此语法不能反馈到表达式计算器中,该计算器旨在尽可能接近源语言,但您可以使用它们使用frame var命令挖掘局部变量-短别名v:

(lldb) v m[0]
(std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>) [0] = (first = "foo", second = 23)
(lldb) v m[0].first
(const std::basic_string<char, std::char_traits<char>, std::allocator<char> >) m[0].first = "foo"

等等。

最新更新