工
工具链实战:Makefile、gdb、valgrind
Makefile · gdb · valgrind
单个文件敲一行 gcc 还行,可项目一旦拆成十个 .c 文件,每次手敲又长又容易漏。这一章给三件"真正上班用得到"的工具:一键编译、单步调试、内存体检。
Makefile:一条命令编译整个项目
Makefile 是个"配方表":写清楚"依赖关系 + 怎么造",以后敲 make 就自动只重编改动过的文件。下面是最小可用版。
Makefile(注意命令行前是一个 Tab,不是空格)
CC = gcc
CFLAGS = -Wall -g -std=c11 # 编译参数
TARGET = app
OBJS = main.o student.o list.o
# 默认目标:造 app
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS)
# 每个 .o 依赖它对应的 .c
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean: # make clean 删掉生成产物
rm -f $(OBJS) $(TARGET)
用法
$ make # 自动编译,只重编改过的文件
$ ./app
$ make clean # 打扫战场
gdb:让程序单步走给你看
程序崩了但不知道死哪一行?用 gdb。前提是编译时加了 -g。常用就四个动作。
| gdb 命令 | 干什么 |
|---|---|
gdb ./app | 加载程序开始调试。 |
b 行号 / b 函数名 | 下断点(break)。 |
run | 跑起来,直到撞上断点。 |
n / s | 下一步(step over / step into 进函数)。 |
p 变量 | 打印某个变量当前的值。 |
bt | 看调用栈:现在怎么一步步跑到这的(backtrace)。 |
quit | 退出 gdb。 |
valgrind:内存体检
怀疑内存泄漏或越界,但肉眼看不出来?把程序丢给 valgrind,它会模拟跑一遍,告诉你哪一行 malloc 了没 free、哪一行读越界了。
用法与典型输出
$ valgrind ./app
==1234== Invalid write of size 4
==1234== at 0x109XXX: main (main.c:12) # 第 12 行写越界了
==1234==
==1234== 4 bytes in 1 blocks are definitely lost in loss record 1
==1234== at malloc (vg_replace_malloc.c:...)
==1234== by main (main.c:8) # 第 8 行 malloc 的没 free
记怎么看 valgrind 报告
别被一堆等号线吓住。只找两类关键词:Invalid read/write(越界读写)和 definitely lost(铁定泄漏)。by main (xxx.c:行号) 那行就是罪魁祸首,回去改那一行就行。
学习资源(都能白嫖)
| 资源 | 特点 | 适合阶段 |
|---|---|---|
| cppreference(C 部分) | 标准库函数权威参考,每个函数都有例子。 | 查 API,随手翻 |
| K&R《C 程序设计语言》 | C 之父亲笔,薄而经典,半小时一篇。 | 学完基础后精读 |
| Learn-C.org | 交互式在线练习,浏览器里直接编译运行。 | 零基础边学边敲 |
| Compiler Explorer(godbolt) | 写 C 代码实时看它变成什么汇编,理解底层神器。 | 学完指针后进阶 |