ASan使程序变慢2–3倍、内存增2–3倍,主因是redzone和shadow memory;TSan开销更大(5–15倍性能损耗、5–10倍内存占用),且需全进程统一启用,不支持混用。

ASan 会让程序变慢多少?内存涨多少?
ASan 运行时比正常程序慢约 2–3 倍,内存占用增加约 2–3 倍。这个开销主要来自两部分:一是为每个分配的内存块周围插入不可访问的 redzone(红区),二是维护一块独立的 shadow memory(影子内存)来实时跟踪每字节的生命周期状态。
实际影响程度取决于代码中内存操作的密集度——比如大量小对象频繁 new/delete、栈上大数组、或密集 memcpy 的场景,ASan 开销会更明显;纯计算逻辑多的模块,影响就相对小。
- 不是所有内存错误都能被 ASan 捕获:它不检测未初始化内存读取(那是
MSan的事) - 启用 ASan 后必须确保链接的是动态 libc++(HarmonyOS 下不支持静态链接
libc或libc++) - 如果 entry 模块没开 ASan,但某个 so 库开了,应用启动直接
CPP Crash,不会等到运行时才报错
TSan 的性能代价远高于 ASan,别在压测环境用
TSan 的典型性能开销是正常程序的 5–15 倍,内存占用涨 5–10 倍。这不是线性增长——线程越多、共享变量访问越频繁、锁粒度越细,TSan 的 runtime 跟踪负担就越重,甚至可能因虚拟内存耗尽而启动失败(尤其在 ArkWeb 初始化 Chromium 内核时已预占大量虚存的场景)。
它不是“加个 flag 就能跑”的工具,而是专用于定位数据竞争这类偶发、难复现 bug 的调试利器。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- TSan 只支持 API Level
12及以上(HarmonyOS Next) - 它能报出死锁、未持锁 wait/broadcast、未持锁 unlock 等问题,但前提是这些同步原语本身被 TSan 插桩识别(比如用的是标准
pthread_mutex_t或std::mutex) -
asan、tsan、hwasan三者互斥,不能同时开启;工程里只要有一个模块启用了 TSan,整个进程都得走 TSan 路径
为什么 ASan/TSan 比 Valgrind 快,但反而更难接入?
因为 ASan 和 TSan 是编译期插桩:它们把检测逻辑直接写进你的二进制里,运行时无需解释执行,所以比 Valgrind(慢 10–50 倍)快一个数量级。但代价是——你必须重新编译所有相关模块,包括所有依赖的 native so 库,并确保 ABI 和 sanitizer 模式完全一致。
常见断点式失败场景:
- so 库编译时没加
-DOHOS_ENABLE_TSAN=on,但主 app 开了 TSan → 启动即 crash - app.json5 里配置了
ASAN_OPTIONS,但 so 库没用-fno-omit-frame-pointer编译 → 报错堆栈只有地址,没有函数名 - TSan 开启后,GPU 渲染模块申请大块虚拟内存失败 → 日志里出现
mmap: Cannot allocate memory
怎么选?看 bug 类型,不是看谁“高级”
怀疑数组越界、use-after-free、内存泄漏?用 ASan。怀疑两个线程改同一个 int counter 导致结果随机?用 TSan。两者混用不仅无效,还会导致构建失败或运行时冲突。
真实项目里最容易被忽略的一点是:Sanitizer 不是上线开关,而是调试探针。它改变内存布局、线程调度行为、甚至触发原本被掩盖的竞争条件——你看到的 crash,可能是 sanitizer 揭露的老 bug,也可能是 sanitizer 自身引入的新干扰。
别指望开着 TSan 跑一天压力测试来“摸底”,它只适合在复现路径明确、能单步触发的 case 上快速定位根因。
















