删死代码不是一行行找——从根节点往下砍
一句话: 项目里堆了大量没人调的函数,分散各处一个一个删容易漏。正确做法:找到"根节点"——最上层入口函数有没有人调。根没人调→整条调用链都是死的,从根往下砍,每个节点确认无依赖再删。
适合谁读:适合嵌入式开发者、单片机初学者及遇到类似问题的工程师
为什么不能一个一个删
嵌入式项目迭代久了,会积累各种死代码:
- 弃用的外设驱动(老芯片换掉了,但老驱动留着)
- 开发中期加的测试功能(后来没用上,但忘了删)
- 同事离职留下的半成品模块
如果看到就删、见一个删一个,容易出两个问题:
漏删:删了 A 函数,但 A 调用的 B/C/D 三个函数没发现,留了一堆无主代码。
误删:删了 A,但 A 其实在另一个文件里被调用了(只是你没搜到)。
正确方法:从根往下砍
第一步:找根节点——谁都没调的最上层函数
# 对每个可疑的函数,搜有没有人调它 grep -r "PWM_Config" *.c # 只在定义处出现?→ 根节点 grep -r "Set_PWM" *.c # 只在 PWM_Config 里调?→ 子节点第二步:画调用链
PWM_Config() ← 无人调用 → 整条链死 └→ Set_PWM() ← 仅 PWM_Config 调 └→ Timer_Config() ← 仅 Set_PWM 调 └→ NVIC_Config() ← 仅 Timer_Config 调根死了,整棵树都是死的。不需要单独验证每个子节点。
第三步:从根往下删,每层确认
// 删 PWM_Config → 搜一遍确认只剩定义和调用 → 删 // 删 Set_PWM → 搜一遍确认只剩定义和调用 → 删 // 删 Timer_Config → ...每删一个,grep确认一次——有人调就停,没人调就继续。
第四步:清理连带的东西
死函数删完后:
| 连带要删的 | 在哪 |
|---|---|
| 结构体里只在死代码中用的字段 | .h文件 |
extern声明 | .h文件 |
#include死代码专用的头文件 | .c文件开头 |
| 中断向量表里死函数注册的条目 | 启动文件 |
踩过的坑
大文件别用 sed 按行号删
死代码和活跃代码可能交错在一起。sed 一刀切容易把活跃代码也干掉。
# 危险:死代码和活跃代码在同一个文件里交错 sed -i '100,200d' driver.c # 可能切掉了活函数用函数名匹配,不要用行号。
# 安全:先用 grep 确认范围,再精确删除 grep -n "DeadFunc" driver.c # 确认行号 # 然后只删这个函数,不是一段行号删完验证残留
# 删完后确认没有残留引用 grep -r "DeadFunc" *.c *.h # 应该只出现在注释里改文件前关掉 IDE
IDE(Keil/IAR/VSCode)可能在后台重写项目文件。你改完一保存,IDE 从缓存恢复了原始内容。改之前关掉 IDE。
总结
| 步骤 | 做什么 |
|---|---|
| 1 | grep -r找根节点(无人调用的最上层函数) |
| 2 | 画出调用链,根死了整链死 |
| 3 | 从根往下逐层删,每层 grep 确认 |
| 4 | 清理结构体字段、extern、include |
| 5 | 关 IDE,删完 grep 验证残留 |
死代码不一定是害,留着不会导致 bug。但删错了会。不确定的时候,宁愿留着。
有用的话点个收藏,下次调试直接用。有问题欢迎评论区交流,看到了都会回。
