C++编译与调试
6/17/25About 6 min
C++编译与调试
一、gcc/g++编译器的使用
1. 基础编译指令
# 编译单个源文件为可执行文件
gcc main.c -o app
# 编译多个源文件为可执行文件
gcc main.c utils.c -o app
# 分别编译源文件为目标文件(.o),再链接
gcc -c main.c # 生成main.o
gcc -c utils.c # 生成utils.o
gcc main.o utils.o -o app # 链接多个目标文件
2. 编译选项
- 优化选项
-O0 # 不优化(默认)
-O1 # 基本优化
-O2 # 常用优化级别(推荐)
-O3 # 最高级优化(可能增加编译时间)
-Os # 优化代码大小
- 调试选项
-g # 生成调试信息(配合gdb使用)
-g3 # 更详细的调试信息
- 警告选项
-Wall # 开启常见警告(推荐)
-Werror # 将所有警告视为错误
-Wextra # 开启额外警告
-pedantic # 严格遵循标准
- C++标准选项
-std=c99 # 使用C99标准
-std=c11 # 使用C11标准
-std=c++11 # 使用C++11标准
-std=c++17 # 使用C++17标准
3. 头文件与库文件选项
- 指定头文件路径
-I/path/to/include # 添加头文件搜索路径
- 指定库文件路径
-L/path/to/lib # 添加库文件搜索路径
-lname # 链接名为libname.so或libname.a的库
- 动态链接与静态链接
-shared # 生成共享库
-static # 强制使用静态链接
- 预处理器选项
-DMACRO # 定义宏(等价于在代码中#define MACRO)
-DMACRO=VALUE # 定义带值的宏
-E # 仅运行预处理器,不编译
4. 高级选项
- 生成汇编代码
-S # 生成汇编文件(.s)
- 生成依赖文件
-M # 生成依赖关系
-MM # 生成不包含系统头文件的依赖关系
-MT target # 指定依赖目标
- 位置无关代码(PIC)
-fPIC # 生成位置无关代码(用于共享库)
二、gdb调试器的使用
1. 启动调试的三种方式
- 调试已编译的可执行文件
# 编译时需加 -g 选项生成调试信息
gcc -g main.c -o app
gdb app # 启动GDB调试app
- attach调试正在运行的进程
# 查看进程PID
ps -ef | grep app
gdb attach <PID> # 附加到目标进程
- 调试核心转储文件(core dump)
# 先配置系统允许生成core文件
ulimit -c unlimited
gdb app core # 分析core文件(需提前设置程序崩溃时生成core)
2. 基础调试命令
- 查看代码
list 或 l # 显示当前行附近的代码(默认10行)
list <函数名> # 显示指定函数的代码
list <文件名:行号> # 显示指定文件的某一行(如 list main.c:20)
- 设置断点(Breakpoint)
break 或 b # 常用断点命令
b <行号> # 在指定行设置断点(如 b 20)
b <函数名> # 在指定函数入口设置断点(如 b main)
b filename.c:func # 在指定文件的函数设置断点
info break 或 info b # 查看所有断点列表
delete <断点编号> # 删除指定断点(如 delete 1)
disable <断点编号> # 禁用断点(保留但不生效)
enable <断点编号> # 启用已禁用的断点
- 运行程序
run 或 r # 启动程序运行(若程序需要参数,可直接跟在r后,如 r arg1 arg2)
continue 或 c # 继续运行程序,直到遇到下一个断点或结束
- 单步执行
next 或 n # 单步执行(不进入函数内部,直接执行函数调用)
step 或 s # 单步执行(进入函数内部,跟踪函数调用)
until 或 u <行号> # 快速执行到指定行(跳出当前循环)
finish # 运行到当前函数返回(跳出函数)
3. 查看与修改变量
- 查看变量值
print 或 p <变量名> # 打印变量值(支持表达式,如 p a + b)
p *指针变量 # 打印指针指向的内容
p &变量名 # 打印变量地址
display <表达式> # 每次单步执行后自动显示表达式值(如 display i)
undisplay <编号> # 取消自动显示(编号由display命令输出)
- 修改变量值
set <变量名>=<值> # 修改变量值(如 set i=100)
p <变量名>=<值> # 等价于set命令(如 p i=100)
- 查看数据类型
whatis <变量名> # 查看变量类型(如 whatis arr)
ptype <变量名> # 查看变量的详细类型定义
4. 调用函数与栈操作
- 调用函数
call <函数名>(参数) # 在调试中调用函数(如 call printf("hello\n"))
查看调用栈
backtrace 或 bt # 查看当前函数调用栈(显示各层函数的调用关系)
frame 或 f <编号> # 切换到指定栈帧(编号从0开始,0为当前栈帧)
up # 向上切换栈帧(调用者方向)
down # 向下切换栈帧(被调用者方向)
5. 条件断点与观察点
- 条件断点
b <行号> if <条件> # 在指定行设置带条件的断点(如 b 20 if i==5)
condition <断点编号> <条件> # 修改已有断点的条件(如 condition 1 i>10)
- 观察点(Watchpoint)
watch <表达式> # 当表达式的值改变时暂停程序(如 watch x)
rwatch <表达式> # 当表达式被读取时暂停程序
awatch <表达式> # 当表达式被访问(读或写)时暂停程序
info watchpoints # 查看所有观察点
6. 其他命令
- 退出调试
quit 或 q # 退出GDB(若程序正在运行,会强制终止)
detach # 从attach模式分离(不终止程序)
- 设置参数与环境变量
set args <参数列表> # 设置程序运行参数(如 set args 10 "test")
show args # 查看已设置的参数
set environment VAR=value # 设置环境变量(如 set environment PATH=$PATH:/new/path)
- 搜索与跳转
search <字符串> # 在代码中搜索字符串(如 search "error")
jump <行号> # 直接跳转到指定行(谨慎使用,可能破坏程序状态)
三、CMake构建
官方文档:https://cmake.org/documentation/
1. 项目基础配置
- 最低 CMake 版本要求
cmake_minimum_required(VERSION 3.10)
- 项目名称与语言(C/C++)
project(MyProject LANGUAGES C CXX)
- 设置 C++ 标准(如 C++11/14/17)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) # 禁用 GNU 扩展
2. 设置编译产物
- 编译可执行程序
add_executable (${_PROJECT_NAME_} ${SOURCES})
- 编译静态库
add_library (${_PROJECT_NAME_} STATIC ${SOURCES})
- 编译动态库
add_library (${_PROJECT_NAME_} SHARED ${SOURCES})
3. 设定C/C++编译器
- 设定C编译器
set(_C_COMPILER_PATH_ "/home/x86_64-linux-musl-native/bin/x86_64-linux-musl-gcc")
set(CMAKE_C_COMPILER ${_C_COMPILER_PATH_})
- 设定C++编译器
set(_CXX_COMPILER_PATH_ "/home/x86_64-linux-musl-native/bin/x86_64-linux-musl-g++")
set(CMAKE_CXX_COMPILER ${_CXX_COMPILER_PATH_})
4. 头文件及库文件选项
- 添加自定义头文件目录
include_directories(${_OPENSSL_HEADER_PATH_})
- 添加自定义库文件目录
link_directories(${_OPENSSL_LIB_PATH_})
- 链接指定库
target_link_libraries(${_PROJECT_NAME_} "stdc++")
target_link_libraries(${_PROJECT_NAME_} "gcc_eh")
5. 调试信息
- 查看当前使用的C/C++编译器
MESSAGE(STATUS "C Compiler: ${CMAKE_C_COMPILER}")
MESSAGE(STATUS "CPP Compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "当前编译模式: ${CMAKE_BUILD_TYPE}") # 输出状态信息
message(WARNING "警告:缺少优化选项") # 输出警告
message(FATAL_ERROR "错误:依赖库未找到") # 终止编译
6. 编译流程及步骤
- 创建构建文件夹
mkdir build
cd build
- 生成构建文件
cmake ..
- 编译项目
cmake --build . --config Release # Windows
make -j4 # Unix 开启4个线程并行编译,-j 默认开启CPU核心个数线程