gdb调试学习笔记

编译时必须要添加-g参数,否则会提示没有找到编译项

在这里插入图片描述
上图中在生成demo1.o文件时我并没有加-g参数,出现以下的提示:
在这里插入图片描述
对这个生成的mian可执行程序gdb调试时是失败的,直接运行了结果,并不会到指定的断点上。
在这里插入图片描述

调试的一些指令

以下代码为测试代码,编译脚本Makefile文件为编译脚本,生成文件为main的可执行程序。

#include <iostream>
using namespace std;

//g++ -o demo1 demo1.cpp
int main()
{
    cout << "hello world" <<endl;
    return 0;
}

编译脚本Maklefile

CXX=g++
CPPFLAGS= -std=c++11
CFLAGS = -g -O2  -Wall -Werror -Wno-unused
edit:demo1.o
	$(CXX) $(CPPFLAGS) $(CFLAGS) -o main demo1.o

demo1.o:
	$(CXX) $(CPPFLAGS) $(CFLAGS) -c  demo1.cpp
.PHONY=clean
clean:
	rm -rf main demo1 *.o
1 启动GDB调试
a. 直接用gdb调试程序:

输入:GDB test【在GDB下运行 test文件】
在这里插入图片描述

b. 挂载运行的程序

ps -ef | grep main获取到运行程序的进程号,启动gdb,用命令attach 进程号挂载程序,如下图:
在这里插入图片描述

2 添加断点
a. 以文件名和行号添加断点

b ParamsTest.cc:356,下图表示,在demo1.cpp的第7行添加断点
在这里插入图片描述

b. 以函数名字添加断点

break function_name,在函数print()上断点,r运行到断点后如下:
在这里插入图片描述

d. 以条件语句添加断点

break 7 if i==99

e. 以条件语句加断点

watch i==99

3 开始运行

run或者r,下图表示开始运行已经断点的程序,执行到第8行(断点处第7行的下一行)
在这里插入图片描述

4 程序停在断点处,单步调试(进入)

s

5 查看当前代码

l, 查看当前行所在位置前后一共10行的代码,如下:
在这里插入图片描述

6 单步调试(不进入)

n或者next, 执行下一步,程序执行完毕。
在这里插入图片描述

7 跳出当前代码(之前跳入调试)

finish

8 程序崩溃,(segmentation fault) 查看栈信息

如下代码示例:

void core_dump()
{
    cout << "数组中的数据为:" << endl;
    int arr[5] = {0, 1, 2, 3, 4};
    for (size_t i = 0; i < sizeof(arr) / sizeof(int); i++)
    {
        cout << arr[i] << ", ";
    }
    cout << endl;
    int a6 = arr[6];
    cout << "数组中第" << arr[a6] << "个数为:" << arr[a6] << endl;
}

编译之后直接运行可执行程序,发生段错误,在已经设置好的目录下生成了core文件,生成core文件后我们开始调试。
在可执行程序所在的目录下执行:gdb main /home/lucifer/cores/core-main-2795-1585060711,如下:
在这里插入图片描述
很容易能够看出在第38行发生了段错误,再查看局部变量的信息得知是a6数据异常导致的错误。

10 切换到第几层, 比如是第一层

frame 1

11 查看当前变量
a. p直接查看变量的值

p _filename
在这里插入图片描述

b. 查看当前栈的局部变量

info locals或者bt full + 栈编号
第一种方式:
在这里插入图片描述
第二种方式:
bt查看所有的栈信息,每个栈信息一行:
在这里插入图片描述
bt full查看所有的栈信息,如下图中有两个栈信息,栈#0是函数print()的信息,#1main函数的信息
在这里插入图片描述
frame n,通过栈编号查看
在这里插入图片描述
f addr,通过栈的地址查看
在这里插入图片描述
up n或者down n向上或者向下移动n个栈,下图向上移动一个栈
在这里插入图片描述
info frame查看栈内的信息,栈信息中可以看一些寄存器的信息
在这里插入图片描述

12 查看当前vector

p *(myVector._M_impl.M_start)@myVector.size()

13 退出gdb

q或者quit
在这里插入图片描述

14 继续运行到下一个断点

c或者continue

15 查看断点信息

info breakpoints
在这里插入图片描述

16 使断点失效

disable b_iddisable 断点id

17 使断点生效

enable b_id:使断点生效

18 删除断点

clear 行号; clear 函数名; delete b_id1 b_id2

19 重新开始调试,可以直接输入r或者run

在这里插入图片描述输入r之后,又开始运行,到了刚才增加的断点第7行处

x命令查看内存

测试代码:

void x_use()
{
    cout << "x查看参数" << endl;
    int arr[] = {0, 22, 1, 4, 5, 7};
    int *pArr = arr;
}

x/x arr:以(x)16进制查看数组arr的内存信息,下面显示的其实是arr[0]的值
在这里插入图片描述
x/10x arr:以(x)16进制查看数组arr的内存信息,一共显示10个,显示当前地址的10个数据,w表示单个以4字节对齐
在这里插入图片描述
x/10d arr:以(d)10进制查看数组arr的内存信息,一共显示10个, 后面的是内存的脏数据
在这里插入图片描述
x/c:以字符形式显示
x/i:以反汇编显示
在这里插入图片描述
x/s:以字符串形式显示

多线程gdb调试

测试代码

//
static atomic_char32_t s_count = 0;
void thread_func(std::string name)
{
    cout << "线程" << name << "启动" << endl;
    while (true)
    {
        s_count++;
        cout << "线程" << name << "s_count= " << s_count << endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void thread_call_1()
{
    shared_ptr<std::thread> t = std::make_shared<std::thread>(new std::thread(thread_func, " 1 "));
    t->join();
}
//

编译后启动gdb调试,b thread_func(std::string name)打断点,r开始运行,到断点之后,info threads查看线程的信息:
在这里插入图片描述
有2个线程正在运行,thread 线程号切换线程:
在这里插入图片描述

命令用法
info threads显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。 前面有*的是当前调试的线程
thread ID(1,2,3…)切换当前调试的线程为指定ID的线程
break thread_test.c:123 thread all(例:在相应函数的位置设置断点break pthread_run1)在所有线程中相应的行上设置断点
thread apply ID1 ID2 command让一个或者多个线程执行GDB命令command
thread apply all command让所有被调试线程执行GDB命令command
set scheduler-locking 选项 command设置线程是以什么方式来执行命令
set scheduler-locking off不锁定任何线程,也就是所有线程都执行,这是默认值
set scheduler-locking on只有当前被调试程序会执行
set scheduler-locking on step在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值