boost::stacktrace::safe_dump_to 输出大小

boost::stacktrace::safe_dump_to output size

我正在尝试使用 boost::stacktrace::safe_dump_to(void*, std::size_t) 函数将堆栈跟踪保存到原始内存,但是函数 returns 写入的堆栈帧数(加上终止帧)- 不是写入的字节数。

这意味着当我来读取这个数据时,我不知道在 boost::stacktrace::stacktrace::from_dump(const void *, std::size_t, const allocator_type &) 的大小字段中放什么。起初我假设我可以使用 sizeof(boost::stacktrace::frame) * frames,但是 frame 类型包含堆分配的内存(std::strings)所以这不起作用。

这个SSCE demonstrates问题:

#include <iostream>

#include <boost/stacktrace.hpp>

int main()
{
    auto buf = std::array<char, 8192>{};
    const auto size = boost::stacktrace::safe_dump_to(buf.data(), buf.size());
    const auto st = boost::stacktrace::stacktrace::from_dump(buf.data(), size);

    std::cout << "ST from dump (" << size << " bytes): " << st << std::endl
              << "ST: " << boost::stacktrace::stacktrace{} << std::endl;


    return EXIT_SUCCESS;
}

它输出:

ST from dump (4 bytes): 
ST:  0# 0x00000000004016A7 in ./a.out
 1# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
 2# 0x0000000000401759 in ./a.out

第二行 'ST' 只是为了显示预期内容。第一行失败,因为我试图将帧数视为字节大小,但显然不是。

那么 API 应该如何使用?

只要在阅读背面使用相同的尺寸:

const auto st = boost::stacktrace::stacktrace::from_dump(buf.data(), buf.size());

毕竟你在写转储时使用了那个限制,所以已知大小比那个小。

Live On Coliru

#include <iostream>
#include <boost/stacktrace.hpp>

int main()
{
    auto buf = std::array<char, 8192>{};
    const auto size = boost::stacktrace::safe_dump_to(buf.data(), buf.size());
    const auto st = boost::stacktrace::stacktrace::from_dump(buf.data(), buf.size());

    std::cout << "ST from dump (" << size << " frames): " << st << std::endl
              << "ST: " << boost::stacktrace::stacktrace{} << std::endl;
}

版画

ST from dump (4 frames):  0# 0x00000000004016B9 in ./a.out
 1# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
 2# 0x0000000000401869 in ./a.out

ST:  0# 0x00000000004017AF in ./a.out
 1# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
 2# 0x0000000000401869 in ./a.out

更新

如评论中所述,文档 here

中有一些关于 safe_dump_to 的花絮

Dumps are binary serialized arrays of void*, so you could read them by using od -tx8 -An stacktrace_dump_failename Linux command or using boost::stacktrace::stacktrace::from_dump functions