gdb调试core并保存std::string到文件

线上有个服务core dump,首先使用gdb打开core文件

gdb bin/xx xx.12769

然后使用backtrace(bt)查看core对应的栈,并使用frame(f)切换到我们业务的层级。

由于core的位置是opencv,调用cv::mean时候core了,我们需要把原始的图片dump出来分析。

业务中有个image_data局部变量保存了入参的图片,下面我们尝试dump出来。

(gdb) p image_data

$3 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, 

    _M_p = 0x7f06d5428c58 "\377\330\377\340"}}

可以看到image_data是std::string,里面有层_M_dataplus._M_p只向了原始的字符串指针。我们需要做的是指定这个字符串长度。 使用网上的一些方法都不太管用,我们来用自己的方法分析。我使用的是gcc8编译,关于std::string可以看看腾讯的这个文章写的比较清楚,gcc的string对象内存布局如下:

preview

所以,我们只需要获取_M_dataplus._M_p的前一个_Rep地址就ok了。

(gdb) p ((std::string::_Rep*)image_data)[-1]

$4 = {<std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep_base> = {_M_length = 30752, _M_capacity = 32711, _M_refcount = -1}, 

  static _S_max_size = 4611686018427387897, static _S_terminal = 0 '\000', static _S_empty_rep_storage = <optimized out>}

可以看到,字符串长度30752,分配大小32711,没有被引用。

接着,我们知道_M_p的地址是0x7f06d5428c58,因此可以用gdb的dump命令把内存数据保存到文件。但是这个命令需要知道内存的起止,我们现在知道了起始位置和长度,需要计算止地址,这个好办。

打开苹果的编程型计算器,输入起始地址

然后转换成十进制

然后加上长度

 

 然后再转换成十六进制就是我们要的地址了。

 然后执行命令

(gdb) dump binary memory /tmp/test.jpg 0x7f06d5428c58 0x7F06D5430478

然后看看/tmp/test.jpg吧~ 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值