嵌入式开发调试利器 | Sanitizer检测器
内容提要
Sanitizer是由Google发起的开源工具集,用于检测内存泄露等问题。它包括了AddressSanitizer、MemorySanitizer、ThreadSanitizer、LeakSanitizer等多种工具。这些工具最初是LLVM项目的一部分,后来也被GNU的GCC编译器支持。Sanitizer的使用例子包括捕捉栈缓冲区溢出问题和使用已释放内存问题。Sanitizer检测器不能同时使用,需要单独挨个检测。
延伸解读
检测器选择需权衡:并非所有Sanitizer都能协同工作
文章明确指出,AddressSanitizer与ThreadSanitizer不能同时使用。这意味着开发者无法通过一次编译同时检测内存错误和线程问题。实际项目中,若代码可能同时存在多种风险,必须分别使用不同检测器进行多轮测试。这增加了调试的步骤,但能避免因工具冲突导致的漏报或误报。
检测能力有侧重:ThreadSanitizer对栈溢出无能为力
通过对比实验,文章发现ThreadSanitizer能准确检测数据竞争,并能以警告级别报告部分使用已释放内存的问题,但无法检测栈缓冲区溢出。即使调整代码执行顺序,栈溢出问题依然被忽略。因此,若怀疑存在栈溢出,应优先使用AddressSanitizer,而非依赖ThreadSanitizer。
AddressSanitizer的终止行为可能掩盖后续错误
文章中的实验显示,AddressSanitizer检测到使用已释放内存的错误后会以错误级别报告并终止程序。这导致位于其后的栈缓冲区溢出问题无法被检测到。若将栈溢出代码放在前面,则能被检测。这提示开发者:当程序存在多个内存错误时,AddressSanitizer可能只报告第一个触发的错误,后续错误需调整代码顺序或分段测试才能发现。
多风险场景下的实用检测策略
文章建议,当程序中存在多种潜在风险时,应使用多个检测器单独挨个检测。每个检测器擅长领域不同,可先初步分析代码,确定大致方向,再选择适合的检测器。例如,怀疑线程问题时用ThreadSanitizer,怀疑内存越界时用AddressSanitizer。这种分步策略虽繁琐,但能更全面地覆盖不同类别的缺陷。
Q&A
Sanitizer是什么?
Sanitizer是由Google发起的开源工具集,用于检测内存泄露等问题。
Sanitizer包含哪些工具?
Sanitizer包括AddressSanitizer、MemorySanitizer、ThreadSanitizer、LeakSanitizer等工具。
如何使用AddressSanitizer进行内存检测?
使用AddressSanitizer时,编译时需加参数 -fsanitize=address。
ThreadSanitizer能检测哪些问题?
ThreadSanitizer用于检测数据竞争、死锁等线程相关问题。
AddressSanitizer和ThreadSanitizer可以同时使用吗?
AddressSanitizer和ThreadSanitizer不能同时使用,需单独检测。
如果程序中同时存在多种风险,应该如何检测?
需要使用多个检测器单独挨个检测,选择合适的检测器进行分析。