CS50 Pset5 Speller:本地Valgrind无错但check50提示Valgrind测试失败
CS50 Pset5 Speller check50 Valgrind项失败排查
现有现象:代码可通过check50除Valgrind测试外的所有检测项,本地手动运行Valgrind无内存泄漏提示,错误摘要显示0 errors from 0 contexts,程序功能运行正常,可按以下方向逐一排查:
- 对齐本地Valgrind测试参数与测试用例
check50运行Valgrind检测时使用的是全量检测参数,且会跑完全部内置测试文本,本地测试不要只用短文本、简略参数跑。直接用以下命令遍历所有测试文本做检测:
不要自行给gcc加-O2之类的优化参数编译,直接用目录下默认的Makefile执行valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -s ./speller texts/austinpowers.txt valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -s ./speller texts/constitution.txt valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -s ./speller texts/pneumonoultramicroscopicsilicovolcanoconiosis.txt valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -s ./speller texts/wordsworth.txt valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -s ./speller texts/her.txt valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -s ./speller texts/lalaland.txt valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes -s ./speller texts/aca.txtmake speller编译,优化等级过高会导致Valgrind漏报内存问题。 - 检查异常分支的资源释放逻辑
绝大多数这类问题都是正常流程的内存释放写对了,但异常分支漏了释放:load函数里如果出现malloc失败、单词读取异常需要提前return false的场景,要把之前已经挂载到哈希表的所有节点逐次释放,同时关闭已经打开的字典文件指针,不能直接跳函数返回check函数里如果申请了临时堆内存(比如存小写转换后的单词),不管匹配结果是true还是false,都要在return前释放掉,不要只在某个分支里free
- 排查非泄漏类的内存错误
Valgrind检测不通过不只有内存泄漏这一种原因,以下问题本地小概率不报、但check50环境会100%捕获:- 存储单词的字符数组长度不足,没有给字符串结束符
\0预留位置,导致越界写 - 遍历哈希表释放节点时,指针移动逻辑错误,出现
use after free(释放完节点后再读节点的next指针) - 全局变量、栈上数组未初始化就被读取
- 存储单词的字符数组长度不足,没有给字符串结束符
最快定位方式:直接点开check50结果里Valgrind失败项的详情日志,里面会完整贴出check50运行环境下的Valgrind报错栈,会直接标注错误对应的代码行号,不需要盲猜问题点。
内容的提问来源于stack exchange,提问作者Prateek Chaturvedi
相关产品推荐
相关产品推荐

