☰
功能还在不等于没漏:拷机要看堆曲线、任务和重连次数
2026/10/16 6:35:01 网站建设 项目流程

副标题:泄漏、碎片、栈溢出不是同一种死机;重连路径最容易漏缓冲
专栏:《嵌入式学生的方案测试课》第 13 篇(稳定性)
前置:第 2 篇堆栈;第 3 篇任务还活着;第 10 篇重连
标签:嵌入式、内存泄漏、RTOS、软件测试、拷机
读者:功能演示过,没看过剩余堆,拷机只会看灯还亮
学完交什么:故意泄漏的堆曲线、正确 free 的对照曲线、2 小时拷机表、一张「不是泄漏」对照
主实验:PC 上 C 程序就能画「只降不回」。有 Hi3861 则板上打印剩余堆。ESP8266 模组侧不一定能打堆,打主控。


0. 这篇结束你能干什么

  1. 能区分:泄漏、碎片、栈溢出、正常常驻缓冲。
  2. 会周期性打印剩余堆,画出「只降不回」和「降了会回」两条线。
  3. 能设计 2 小时拷机:每 10 分钟一行,看死机、看门狗、堆、任务、重连次数、误控、采样中断。正文告诉你 12 小时怎么排班,不必今晚扛到天亮。
  4. 能读懂公开 ReleaseNote 为什么要把 mjpeg 改成按节点申请:那是碎片,不是「内存变小一点」。

1. 为什么灯还亮也可以不及格

客户验收隔夜。第二天板子死了,或还能 ping 但一录像就复位。你昨天离开时灯是亮的。

泄漏的典型形状:功能仍在,剩余堆单边下降,第 N 小时 malloc 失败,复位或静默停发。重连路径最爱漏:每次断网申请一条缓冲,成功路径 free 了,失败路径忘了。

所以拷机不是「开着过夜」,是带观察点的过夜。


2. 最小原理

2.1 四张图,不要混

名字形状典型原因现场
泄漏剩余堆随时间或随次数单调下降,不回来malloc/free 不成对;失败路径漏 free越跑越少,最后申请失败
碎片总空闲看起来够,但没有连续大块反复申请不同大小;一次性要大块某一功能(720P、mjpeg)突然失败
栈溢出往往很快死,不一定越跑越慢大数组在栈上、递归、中断嵌套死机点固定,和运行时长弱相关
常驻启动后下降一截然后平缓冲池、协议栈、图片帧不是缺陷

第 2 篇堆栈 5 点:栈自动、堆手动。拷机看的是堆的时间序列,以及任务还在不在(第 3 篇)。

2.2 失败路径比成功路径更漏

伪代码:

buf = malloc(n); if (connect() != 0) return; // 漏 free send(buf); free(buf);

测泄漏要专打失败:错密钥、断网、超时。只测 happy path 会得出「无泄漏」的假阴性。

2.3 看门狗、死机、任务卡住

拷机观察列:

  • 整板复位(启动日志再次出现)
  • 看门狗(日志有 WDT)
  • 剩余堆数字
  • 任务:采集是否还按周期;AT 是否还响应(第 3 篇阻塞)
  • 重连次数(计数器,不要凭感觉)
  • 误控:灯自己亮、阀自己动
  • 采样中断:时间戳间隔从 1s 变成 5s

灯亮且 ping 通,但采样停了,仍是失败。

2.4 公开缺陷语言(对齐 ReleaseNote)

FPV ReleaseNote 公开修过:

  • mjpeg 一次性申请大空间导致碎片,改成按节点申请
  • h264 图像过大空间不足死机
  • lcd line_buf 申请大小错误死机
  • 录风者 sd 格式化概率死机

测试该写:「改分辨率/开辅码流后剩余堆与死机率」,不是「我去改 ISP」。


3. 手把手实验

3.1 PC 上故意泄漏(必做)

/* leak_demo.c 教学用,不要拷进产品 */#include<stdio.h>#include<stdlib.h>#include<string.h>#ifdef_WIN32#include<windows.h>#definesleep_ms(x)Sleep(x)#else#include<unistd.h>#definesleep_ms(x)usleep((x)*1000)#endifintmain(void){inti;for(i=1;i<=20;i++){void*p=malloc(64*1024);(void)p;/* 故意不 free */printf("i=%d alloc 64k (leaked)\n",i);fflush(stdout);sleep_ms(200);}return0;}

再写free_demo.c:同样循环,free(p)。

Windows 任务管理器看进程工作集,或用简单计数:泄漏版 20 次后占用明显高。更干净:自己维护outstanding计数。作业要的是曲线意识:泄漏版单调升(占用)或板上单调降(剩余堆)。

有 POSIXmallinfo或 MCUxPortGetFreeHeapSize就打印剩余。没有就用计数器模拟:

remaining = remaining - 64; // 泄漏 remaining = remaining; // 正确 free 后回到基线附近

把 20 个点画进labs/week13/heap-leak.csv和heap-free.csv。

3.2 碎片直觉(不必上板)

讲清楚即可:总空闲 40KB,要 32KB 连续块,中间碎成 20×2KB,失败。ReleaseNote 的 mjpeg「一个一个节点申请」就是避免一次性连续大块。作业画一张示意图,不要求在 MCU 上复现碎片。

3.3 断网重连 100 次专看堆(能做多少写多少)

有 Hi3861:循环断热点 / 关 Wi-Fi,每次打印剩余堆和重连结果。目标 100 次;USB 不稳就 20 次,报告写次数。

期望:成功和失败两种路径下,剩余堆回到同一平台,而不是每次 -128 字节。

ESP8266 模组:模组内部堆你看不见。测主控:每次 AT 会话你是否泄漏了行缓冲。

3.4 2 小时拷机(必做排班)

不必 12 小时一次做完。2 小时是本周及格。12 小时用排班:晚上 22:00 开,早上 10:00 收,中间睡眠,但日志要自己打:每 10 分钟一行,用 RTC 或电脑侧脚本(第 14 篇)。没有脚本就闹钟起来抽查四次,诚实写抽查。

表头:

时间 剩余堆 AT探活 RSSI IP MQTT/HTTP 重连累计 复位累计 备注

注入可选:中途关 2 分钟热点,看重连后堆是否回去。

失败判据(示例,产品有规格则用规格):

  • 复位 ≥1
  • 剩余堆相对起始下降 >30% 且不回
  • 连续 3 个采样周期中断
  • 误控

灯亮不是通过准则。

3.5 12 小时怎么排班(教方法,本周不强制做满)

21:50 环境表、起始堆、版本、天线照片 22:00 开始;确认业务基线 22:10 第一行表 过夜 电脑不休眠;串口日志重定向到文件;电源不要省电 次日 打开日志看有无重启横幅、堆是否单调 08:00 人工确认仍活着 10:00 结束,贴曲线

宿舍断电、电脑休眠会毁掉实验。毁掉就重来,不要把空洞日志写成通过。


4. 缺陷单范文

标题:【内存】12 小时拷机剩余堆 40KB→6KB,功能尚在,第 13 小时 malloc 失败复位 环境:Hi3861 农业终端,固件 ____,MQTT KeepAlive 60,每 2s 上报 步骤:无额外打流;每 10min 打印 free heap 期望:堆在启动平台 ±10%,无复位 实际:单调下降;13h08min 复位;启动日志 malloc fail 附件:heap.csv 曲线;uart 含复位横幅 初步分层:堆泄漏(疑似重连或上报路径)。不是栈溢出(运行时长相关)。待开发核对未 free 路径。

2 小时若只降很少,不要假装 12 小时结论。写「2h 未暴露,12h 未做」。


5. 泰芯对照

公开事实测试语言
mjpeg 改节点申请防碎片开录像/拍照后是否还能申请大块;失败是否随时间
h264 空间不足死机升分辨率/开辅码流的拷机
lcd line_buf 大小错误死机改分辨率后的冒烟+拷机
FPV 文档:事件注册消耗 heap,退出要 untake反复配网/插拔是否泄漏事件节点
初始化里 Socket 阻塞应放到任务拷机看主任务是否被堵(第 3 篇)
低功耗循环看 heap(第 16 篇)休眠唤醒后堆是否回到平台

学生板没有 mjpeg 就用「反复 malloc 不同大小」在 PC 上讲碎片。


6. 30 秒口径

拷机要看堆曲线、任务、重连次数、复位,不看灯亮。
泄漏是剩余堆只降不回;碎片是总空闲够但连续块不够;栈溢出常常立刻死。
重连失败路径最容易漏 free。
我做了 2 小时带表拷机(12 小时若没做会说明)。
ReleaseNote 里的死机很多是空间和碎片,测试要对着分辨率和功能组合做。


7. 作业

labs/week13/ heap-leak.csv heap-free.csv not-a-leak.md # 栈溢出/常驻/碎片对照 soak-2h.md # 每 10min 一行,没有就写抽查时间 reconnect-heap.md # 次数如实 bug-or-clean.md

验收:两条曲线方向相反或平台对照明显;拷机表不是「灯亮」一句话。


8. 自测题

  1. 剩余堆启动时降 8KB 然后 2 小时平,算泄漏吗?
  2. 为什么只测配网成功路径会漏测泄漏?
  3. 看门狗复位和 malloc 失败复位,日志上如何区分?
  4. 碎片时xPortGetFreeHeapSize可能仍显示够用,为什么功能失败?
  5. 2 小时通过能否宣称 12 小时通过?
  6. ESP8266 模组测谁的堆?
  7. 拷机中途电脑休眠,数据怎么处理?
  8. 误控为什么要单独列?

9. 学生常见翻车

  1. 拷机只看灯。
  2. 把死机都写成泄漏。
  3. 没有起始堆,只有结束感觉。
  4. 12 小时日志被休眠截断仍写通过。
  5. 把演示用的 leak_demo 留在产品工程。
  6. 简历写精通内存检测,实际没有 csv。

10. 下一篇预告

第 14 篇:《方案测试的 Python 只有一种正当用法:替你发 AT、收日志、填表格》。

2 小时一行一行手抄会疯。下一篇 50 到 80 行 pyserial:错密码 10 次,统计耗时和 ERROR 原文。板端仍是 C。


附录 A. 自测题参考答案

  1. 像常驻,不是泄漏。
  2. 失败路径常漏 free。
  3. WDT 有看门狗打印;malloc 失败常有申请失败日志或返回 NULL 后崩溃栈。都以原文为准。
  4. 总空闲是碎片之和,malloc 要连续块。
  5. 不能。
  6. 主控堆;模组内部除非有 AT 查堆。
  7. 实验无效,重做。
  8. 稳定且「还活着」也可以伤害用户;功能错误不是死机。

附录 B. 公开资料

  • TXW82x FPV ReleaseNote:mjpeg 碎片、h264/lcd 死机
  • FPV 开发文档:heap 初始化、事件消耗 heap、CPU1 heap 配置
  • 第 2、3 篇

(第 13 篇完)


11. 曲线怎么画才像测试而不是手绘心情

csv:

t_s,free_heap_or_outstanding_k,event 0,40,start 600,39,none 1200,38,reconnect 1800,30,reconnect_fail_path

用 Excel / LibreOffice 散点图。纵轴写单位:剩余堆 KB 或 outstanding KB。标题含版本。泄漏:整体右下(剩余)或右上(占用)。正确 free:锯齿,每次回到平台。

没有 MCU 堆函数:PC 上用计数器模拟仍然算本篇「曲线意识」及格,但第 18 篇 SOAK 不能写「已证明无泄漏」,只能写「PC 演示 + 板上未采样堆」。

Hi3861 常见HiLink或自己在应用里printf("heap=%u\n", remaining);。找不到 API 就问课程工程是否已有 shell。不要臆造函数名写进博客当原厂 API。


12. 重连 20 次最小脚本逻辑(人也可以按键)

for i in 1..20: 记录 heap0 关热点 5s 开热点 等到 GOT IP 或 30s 失败 记录 heap1、结果、i 期望:heap1 回到 heap0 ± 边限 失败:每次 -n 字节,20 次后明显台阶

边限要写死,例如 ±2KB(协议栈瞬时占用)。不要用眼睛看「差不多」。


13. 栈溢出对照实验(可选,PC)

voidboom(void){charhuge[1024*1024];/* 教学:大数组在栈上 */huge[0]=1;boom();}

跑起来会很快崩。和泄漏对照:泄漏要时间或次数;栈溢出常常第一次深递归就死。拷机 2 小时才死,优先堆和碎片,不要第一句「栈溢出」。

中断里 malloc、大 printf:第 2 篇。拷机若只在 Wi-Fi 中断高峰死,再怀疑中断栈。


14. 公开 ReleaseNote 怎么写成测试用例

公开修复学生/到岗用例
mjpeg 按节点申请连续拍照 100 张,中间看是否仍能申请;失败是否随时间
h264 空间不足死机升分辨率或开辅码流 30min
lcd line_buf 大小改分辨率冒烟
sd 格式化死机格式化 10 次 N/M
720P 辅码流未编码打开辅流 RTSP 检查有无画面(第 16 篇)

无摄像机:这些写在 week16 映射表,不写进 week13「我测过」。


15. 2 小时表空行示例

22:00 heap=40k AT=OK RSSI=-50 IP=yes MQTT=yes reconn=0 rst=0 22:10 40k OK -51 yes yes 0 0 22:20 39k OK -50 yes yes 0 0 # 1k 波动,观察 22:30 关热点注入 22:32 38k OK n/a no no 1 0 # 掉线中 22:35 40k OK -52 yes yes 1 0 # 回来,堆回到平台 —— 好 00:00 仍 40k 无复位

若 22:35 堆停在 32k 再也不回:停实验,提单,不必硬撑 2 小时装完整。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询