c++ sanitizers开销 c++ asan/tsan对性能影响多大

千静君_8135

千静君_8135

2026-03-23

199人浏览

原创

c++oding="utf-8" ?>

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

c++ sanitizers开销 c++ asan/tsan对性能影响多大

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++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 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 上快速定位根因。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

6039

3

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.08.29

2965

6

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.29

3788

10

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.29

2645

10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

5487

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2388

6

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

5487

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2388

6

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

4018

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习