解决思路:

  确定破坏地址值的位置。就是将错误地址当作数据,寻找是在哪里将这个数据写到这个地方的。所以我们寻找写入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

Java gdal 融合_gdb

#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

Java gdal 融合_ubuntu_02

Java gdal 融合_段错误_03

 

调试中的断点
在实际调试中,我们一般会用到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 收集一些发生段错误时的信息。

内核生成 core dump file