小白学Epoll网络编程3 在linux下调试程序

kisaragi 2026-06-07 17:44 1


我们这里使用一台Ubuntu24虚拟机,vscode使用ssh连接到这台机器,然后就可以开始调试了


命令


 g++ -o server ./server2.cpp ./common/common.cpp  -I . 
g++ client.cpp -o client


经历了1和2后我们现在已经有了能够运行的代码,那么如何在linux上使用gdb调试他呢?不能一直用print然后看输出来调试吧, 我们要有单步 堆栈和变量!本节就是总结在linux上的调试方法(针对单文件 项目的我还没学)^-^


我们使用g++在linux上进行调试,首先我们要先编译出一个debug版本,这里从基础说起


通用知识


如何编译一个程序


我们的目录结构是


├── common
│ ├── common.cpp
│ └── common.h
└── server.cpp

其中的结构是server.cpp include了common.h,common.cpp又是common.h的实现


g++ A.cpp B.cpp -o output -I .

这里涉及到一些编译原理的内容,因为编译器实际上并不会单独处理头文件(头文件不是编译单元),他只处理.cpp,头文件只是一种便利的声明,在被include到文件后会被展开,如


// header.h
void functionA();
void functionB();

// impletion.cpp
#include "header.h"
void functionA(){
实现
}
void functionB(){
实现
}

// main.cpp
#include "header.h"
int main(){

}

实际上主main和impletion会被展开成


// impletion.cpp
void functionA();
void functionB();
void functionA(){
实现
}
void functionB(){
实现
}

// main.cpp
void functionA();
void functionB();
int main(){

}

如果你自己每个文件都手敲声明的话比较麻烦,所以c++允许你写到一个单独的文件里然后include他们。但是对编译器来说,在头文件被展开后就不单独看了;到了编译这一步头文件已经被展开到各个实际的文件里了。所以回到刚才的话题,我们要传给g++的参数是server.cpp和common.cpp,即头文件的实现文件和主文件。


-o表示你要输出的二进制的文件名,如output,-I表示搜索头文件的根目录,编译器在展开头文件的阶段会找include提到的文件名;我们的头文件放在当前文件夹的common下,就从当前文件夹开始搜索,写common也行,但是以后可能还有别的文件夹,直接从当前文件夹开始方便以后扩展。


如何编译出debug版本的程序


主要是两点




  • 添加调试信息 -g




  • 关闭大部分优化 -O0




g++ A.cpp B.cpp -o output -I . -g -O0

-O(大写)后面跟的数字是优化等级,可以是0 1 2 3 s等等,代表不优化/基础/通用/激进/体积


我们一般的release版本优化的等级就是-O2, debug版本自然要比2低,这里直接选0, 防止优化过度导致调试的时候断点乱跳/缺失信息


额外的警告


为了开启所有警告还要加上




  • -Wall 所有常见警告(不是所有警告 是所有常见)




  • -Wextra 额外警告




  • -Wpedantic 迂腐的 严格的检查是否符合指定的c++标准,无扩展无非标准写法,有的话警告




g++ -std=c++17 A.cpp B.cpp -o output -I . -g -O0 -Wall -Wextra -Wpedantic

最终的命令变成了这样


kisaragi@ubuntu24:~/Documents/Epoll$ g++ -std=c++17 server2.cpp common/common.cpp -g -O0 -Wextra -Wall -Wpedantic -o testDebug

编译成功 我们得到了testDebug二进制文件


古法 直接使用GDB


打开你的终端,使用gdb 二进制文件 命令来调试


可以通过file 二进制文件 来查看二进制的信息



正常的应该是with debug_info, not stripped,表示有调试信息,符号未被剥离,这里我们自己编的,应该不会错



启动命令,正式进入到gdb的界面中


但是还没显示代码,按ctrl+x后按a键打开代码显示,效果如下,看起来就清晰多了



gdb里的操作都是通过在(gdb)后面打命令实现的,如next, step,break等等;


gdb有很多命令,对于习惯windows调试的我们来说,首先要找出怎么打断点,怎么继续,怎么进入函数, 怎么查看堆栈


流程基础操作


F5继续-->continue
F10下一行-->next
F11进入-->step

我们尝试在main上打一个断点,打断点的命令是break 函数名或者行号,我们直接berak main(),就在main函数上打了个断点,




代码旁边也会显示一个小小的标志,现在可以直接将程序运行起来, 命令是run,等待一会,程序就会断在main第一行了



B+旁边的>角标就是当前行的指示器,我们输入两个next,让他运行到190行,然后看看threads的内容,查看变量的内容是


也可以直接通过start来启动,他的作用和在main上打个断点然后run是一样的


查看变量


print 变量



可以看到目前还没有内容,这是对的,因为刚初始化,监视变量也很简单,使用watch 变量 就可以进行监视,watch threads,当threads被改变时就会断住。


想要删除断点/监视也很简单,使用 info breakpoints查看所有断点



这里可以看到有我们在main里打的,还有刚刚watch的变量,然后我们就可以通过disable 编号 或者 delete 编号来编辑了,如这里删除3号断点,使用delete 3,再查看就没有了


断点操作


break 行号/函数名()  打断点
info breakpoints 查看断点
delete 断点


现在我们随便进一个函数看看,比如threads.push_back()的push_back方法,先运行到这一行,然后输入step就可以进入了


进出函数


step 相当于f11进入
finish 相当于shift+11出函数


成功进入,不想看了就输入finish,就可以进入上一级,相当于shift+f11, 如果你已经step进入很深了,需要多几次才能出去。也可以直接在外面打断点然后continue,和我们在windows上使用都是一样的


调用堆栈


bt或backtrace


常用的就这些命令,玩够了,打quit直接退出


使用vscode


直接使用vscode的remote ssh插件连接到你的服务器,打开文件夹(关于这个插件的使用可以网上搜教程)



终端里tree一下(tree .),复制文件夹结构


├── common
│ ├── common.cpp
│ └── common.h
└── server.cpp

在你的源码目录下新建一个.vscode文件夹,里面新建个launch.json,然后打开ai:


我想要用gdb调试程序,需要/不需要编译,给我写一个vscode里的launch.json,操作系统是xxx,
文件夹结构如下:
├── common
│ ├── common.cpp
│ └── common.h
└── server.cpp



ai直接拿捏,这里因为我说需要编译, ai把tasks.json也补上了,都拷贝进来就好了


然后打开你的源代码,在vscode里按F5,选择使用g++或类似的选项(使用gdb?可能),ai的配置写的没错就可以顺利启动了



这时直接就可以看到堆栈,断点,监视,变量等信息,比gdb要现代化的多,但他的信息其实也是从gdb里取的,只是换了种展示形式;现在你可以像在windwos里一样调试程序了


^-^本节完

最新回复 (7)
  • learn_rust_and_cpp 06-07 17:46
    1

    作为2014年入行的linux 后端 我支持一下你的古法编程; 从原理出发,棒棒的

  • kisaragi 楼主 06-07 18:12
    2

    膜拜老资历大神 还在慢慢学习中 ^-^

  • 皮卡丘不是竹鼠 06-07 18:54
    3

    虽然我完全看不懂,但是还是支持大佬,现在我也正在尝试写笔记,学习编程

  • rose 06-07 19:48
    4

    我感觉有了ai之后我完全不愿意去学习这些东西了

  • kisaragi 楼主 06-08 09:38
    5

    就是因为有ai了学不下去我才尝试写下来的 ^-^

  • kisaragi 楼主 06-08 09:41
    6

    不知道各位佬友有没有这种感受, AI时代自己能写的代码越来越强了,自己的脑容量却越来越小了,感觉学习东西变的很慢,甚至会觉得: AI能做就可以了,我自己会不会都行,查嘛 ^-^。
    我个人算是使用vibe coding比较早的,感觉已经深受“荼毒”了,在尝试了无数方法之后,我想到了过去的朋友在知乎给别人解答问题,做了两年也变得很厉害了;
    其实这种办法就是费曼学习法,即强…


    加油 我也是学不进去东西才开始写笔记的 ^-^

  • 皮卡丘不是竹鼠 06-08 09:44
    7

    我也已经在开发调优频道发布了自己的学习笔记,希望我们一起加油一起进步

* 帖子来源Linux.do
返回