解决思路:
确定破坏地址值的位置。就是将错误地址当作数据,寻找是在哪里将这个数据写到这个地方的。所以我们寻找写入0x676e6964这个数据的地方。
sudo gdb attach 1592
gdb --pid `ps aux|grep Release|grep mediasoup-worker|awk '{print $2}'`
gdb --pid `ps aux|grep Release|grep mediasoup-worker|awk '{print $2}'` -x break.dp
以下是工作中常用的gdb命令
设置启动参数
set args -c conf/rtc.conf
#gdb查看内存区命令
x/5ub Buf
0x7ffff619f010: 0 0 0 1 6
x/16xb raw->payload 16进制
watch
watch (*p) 是 p 所指的内存的内容, 查看地址,一般是我们所需要的。
设置断点
b HttpSendProcess::httprequest
b HttpSendProcess.cpp:37
# break line-or-function if expr
b 229 if ptGbMsgOut->eSipMethod == SIP_METHOD_MESSAGE
break x:20 if strcmp(y, "hello") == 0
break x if ((int)strcmp(y, "hello")) == 0
#某些实现中,gdb可能不知道strcmp的返回类型。
保存断点
save breakpoint fig.dp
gdb hello2 -x fig.dp
gdb调试core文件
gdb a.out core.9775
set args -i input.mp4 -vf transform=input_stereo_format=MONO:w_subdivisons=4:h_subdivisons=4:max_cube_edge_length=512 -qscale 20 output.mp4
条件断点
b 229 if ptGbMsgOut->eSipMethod == SIP_METHOD_MESSAGE
调试中的断点
在实际调试中,我们一般会用到3种断点:普通断点、条件断点和数据断点。
普通断点就是我们添加的断点除去条件断点和硬件断点的断点。
数据断点是被监视的内存值或者变量值发生变化时触发的断点,前面介绍watch命令时添加的部分断点就是数据断点。
条件断点就是满足某个条件才会触发的断点。
添加条件断点的命令是break [lineNo] if [condition],其中lineNo 是程序触发断点后需要停的位置,condition 是断点触发的条件。
eg. break 11 if i==5000
添加条件断点还有一种方法,就是先添加一个普通断点,然后使用“condition 断点编号 断点触发条件”这样的格式来添加。
—————
设置gdb产生core文件
高手指教:
如何设置能够生成core 文件,与终端无关
即,程序启动,关闭终端,当程序死掉(段错误)后能够生成core文件。
在
/etc/security/limits.conf (中设置 redhat衍生系linux)
/etc/security/limits.conf
* soft core unlimited
* hard core unlimited
root soft core unlimited
root hard core unlimited
source /etc/profile
ulimit -c unlimited
sudo systemctl disable apport.service
文件生成目录:vi /etc/sysctl.conf ,新增:kernel.core_pattern=core-%p,
使生效: sysctl -p
kernel.core_uses_pid = 1
kernel.core_pattern = /corefile/core-%e-%p-%t
或
/etc/profile中的:
# No core files by default
ulimit -S -c 0 > /dev/null 2>&1
bt:打印堆栈信息
where: 定位core的地方
f n: 进入指定的堆栈
p 变量名:打印变量名,查看错误情况
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
void segv_handler(int signo)
{
printf("in segv_handler\n");
while (signo) {
sleep(1);
}
}
int main(int argc, char *argv[])
{
char *pointer = NULL;
signal(SIGSEGV, segv_handler);
*pointer = 'c';
return 0;
}
在这里我们可以利用 SIGSEGV 信号来让程序在产生段错误时停住。具体的实现方法是调用 signal 函数注册 SIGSEGV 信号的处理函数,将这个处理函数写成一个死循环。这样当程序出现段错误的时候,内核向程序发送 SIGSEGV 信号,预先注册的信号处理函数被调用,程序停住。
我使用上面的代码验证上述方法是否可行。
查看代码,可以看到第 21 行就是出问题的地方。
21 *pointer = ‘c’;
使用这种方法,我们可以让程序在出现段错误的时候停下来,这样我们就能够使用 gdb 收集一些发生段错误时的信息。