【发布时间】:2018-07-27 02:16:13
【问题描述】:
我想使用 gdb 查看 boost::multi_index(version 1.67.0) 包含的数据。
首先我尝试了https://github.com/ruediger/Boost-Pretty-Printer。
似乎不支持hashed_unique 等哈希索引。
我注意到,如果第一个索引是受支持的类型,例如 sequenced,则 Boost-Pretty-Printer 可以正常工作。
但是,我现在无法编辑代码。我需要调试一个核心文件和一个二进制可执行文件。
我试图用散列索引了解multi_index的内部结构。
我写了以下测试代码:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
namespace mi = boost::multi_index;
struct t_hash{};
using elems = mi::multi_index_container<
int,
mi::indexed_by<
mi::hashed_unique<
mi::tag<t_hash>,
mi::identity<int>
>
>
>;
int main() {
elems es { 0x12, 0x34 };
return 0; // set break point here and (gdb) p es
}
https://wandbox.org/permlink/UtMfVRI4rT5AXUOZ
当我打印 es 时,(gdb) p es 得到以下输出:
$1 = {
<boost::base_from_member<std::allocator<boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<int, std::allocator<int> >, boost::multi_index::detail::hashed_unique_tag> >, 0>> = {
member = {
<__gnu_cxx::new_allocator<boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<int, std::allocator<int> >, boost::multi_index::detail::hashed_unique_tag> >> = {<No data fields>}, <No data fields>}
},
<boost::multi_index::detail::header_holder<boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<int, std::allocator<int> >, boost::multi_index::detail::hashed_unique_tag>*, boost::multi_index::multi_index_container<int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::identity<int>, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<int> > >> = {
<boost::noncopyable_::noncopyable> = {<No data fields>},
members of boost::multi_index::detail::header_holder<boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::index_node_base<int, std::allocator<int> >, boost::multi_index::detail::hashed_unique_tag>*, boost::multi_index::multi_index_container<int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::identity<int>, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<int> > >:
member = 0x55555576ee70
},
<boost::multi_index::detail::hashed_index<boost::multi_index::identity<int>, boost::hash<int>, std::equal_to<int>, boost::multi_index::detail::nth_layer<1, int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::identity<int>, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<int> >, boost::mpl::v_item<t_hash, boost::mpl::vector0<mpl_::na>, 0>, boost::multi_index::detail::hashed_unique_tag>> = {
<boost::multi_index::detail::index_base<int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::identity<int>, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<int> >> = {<No data fields>},
members of boost::multi_index::detail::hashed_index<boost::multi_index::identity<int>, boost::hash<int>, std::equal_to<int>, boost::multi_index::detail::nth_layer<1, int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::identity<int>, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<int> >, boost::mpl::v_item<t_hash, boost::mpl::vector0<mpl_::na>, 0>, boost::multi_index::detail::hashed_unique_tag>:
key = {
<boost::multi_index::detail::non_const_identity_base<int>> = {<No data fields>}, <No data fields>},
hash_ = {
<boost::hash_detail::hash_base<int>> = {
<std::unary_function<int, unsigned long>> = {<No data fields>}, <No data fields>}, <No data fields>},
eq_ = {
<std::binary_function<int, int, bool>> = {<No data fields>}, <No data fields>},
buckets = {
<boost::multi_index::detail::bucket_array_base<true>> = {
<boost::noncopyable_::noncopyable> = {<No data fields>},
},
members of boost::multi_index::detail::bucket_array<std::allocator<int> >:
size_index_ = 0,
spc = {
<boost::noncopyable_::noncopyable> = {<No data fields>},
members of boost::multi_index::detail::auto_space<boost::multi_index::detail::hashed_index_base_node_impl<std::allocator<char> >, std::allocator<int> >:
al_ = {
<__gnu_cxx::new_allocator<boost::multi_index::detail::hashed_index_base_node_impl<std::allocator<char> > >> = {<No data fields>}, <No data fields>},
n_ = 54,
data_ = 0x55555576ee90
}
},
mlf = 1,
max_load = 53
},
members of boost::multi_index::multi_index_container<int, boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<t_hash, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::identity<int>, mpl_::na, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<int> >:
node_count = 2
}
我找到了node_count = 2。似乎元素的数量。我尝试挖掘成员变量。例如)member、buckets 等。但是目前我找不到0x12和0x34的数据。
我如何获得它们?
编辑:2018/07/28 11:51 JST
感谢 cmets,我找到了解决方案。我根据 cmets 总结了两种方法。
基于@sehe 方法的运行时共享库加载,
- 将调试打印函数 (
debug_print()) 编写为共享库 (dp.so)。 - 运行 gdb。
gdb target_executable_file - 做
set environment LD_PRELOAD ./dp.so。 - 设置断点。
- 做
r - 当断点命中时,执行
call debug_print(data)。data是您要查看的目标。
这种方法不需要重新编译目标。但是,当我加载核心文件时,debug_print() 不再在内存中。所以这种方法不适用于核心文件。
我正在寻找加载核心文件后强制加载dp.so,但到目前为止我找不到路。
使用 gdb 跟踪 multi_index 的内部结构
这种方法适用于核心文件。 这种方法基于@Joaquín M López Muñoz 的评论。
- 使用核心文件运行 gdb。
gdb target_executable_file core_file. - 执行以下命令来访问数据。
T是 multi_index 的元素类型。data是 multi_index 容器变量。N是索引数。
第一个数据
p *(T*)((char*)(*data.member).prior_ - sizeof(T) - 0x10 * (N - 1))
第二个数据
p *(T*)((char*)(*(*data.member).prior_).prior_ - sizeof(T) - 0x10 * (N - 1))
...遵循相同的模式。
非常感谢@sele 和@Joaquín M López Muñoz !!
编辑:2018/07/28 15:22 JST
我为 Boost-Pretty-Printer 实现了散列索引支持。它基于上述方法。
我为此发送了拉取请求:
https://github.com/ruediger/Boost-Pretty-Printer/pull/36
编辑:2018/07/28 15:42 JST
我知道 0x10 是什么意思。它是指针大小乘以 2。所以在 64 位环境中,64 位 = 8 字节,8 * 2 = 16 = 0x10。 32bit环境下32bit = 4byte, 4 * 2 = 8 = 0x08。
我还更新了拉取请求。
编辑:2018/08/02 09:30 JST
最后,我发送了两个拉取请求,它们都被合并了。现在,我们可以简单地使用 Boost-Pretty-Printer 并打印以 hashed_index 作为第一个索引的 multi_index 容器。
https://github.com/ruediger/Boost-Pretty-Printer/pull/36
https://github.com/ruediger/Boost-Pretty-Printer/pull/37
这是内部结构和迭代算法:
【问题讨论】:
-
也许您可以将您的更新推广为答案。我很乐意将我的赏金奖励给您为获得这些拉取请求所做的努力。当然,您可以保持接受的答案没有问题,希望额外的关注也能从中受益。
-
@sehe,感谢您的评论。我可以看到上面的消息
This question has an open bounty worth +250 reputation from sehe ending in 4 days.。我已经阅读了赏金的帮助页面。但我不明白我能做什么。如何推广我的更新以回答?我需要自己发布新答案吗?或者有什么方法可以设置我的编辑回答? -
确实,我的意思是您可以根据您在问题中编辑的信息手动创建答案,抱歉我的措辞令人困惑。
-
好的,我会尽快发布我的答案。
标签: c++ boost gdb multi-index