一、ASan 是什么ASan 全称 AddressSanitizer通常称为地址消毒器是一种运行时内存错误检测工具。主要用于检测 C/C 程序中的非法内存访问问题。它通过编译器插桩Instrumentation和运行时库Runtime Library工作。与 GDB 的区别GDB用于调试程序查看变量、调用栈、断点和崩溃现场。ASan用于检测内存错误并报告错误类型、访问位置及相关内存分配/释放位置。二、ASan 能检测的常见问题1. Heap Buffer Overflow堆内存越界使用 malloc/new 申请的堆内存访问超出申请范围的地址。例子char *p malloc(10); p[10] A; // 越界合法下标为 0~92. Stack Buffer Overflow栈内存越界访问局部数组或栈上对象的边界之外。例子int arr[5] {0}; arr[5] 100; // 越界合法下标为 0~43. Global Buffer Overflow全局变量越界访问全局数组或静态存储区对象的边界之外。4. Use After Free释放后使用内存已经通过 free/delete 释放程序仍然通过旧指针访问它。例子int *p malloc(sizeof(int)); free(p); printf(%d, *p); // 错误释放后继续访问注意free(p) 不会自动把指针 p 置为 NULL。5. Double Free重复释放同一块动态内存被释放两次。例子int *p malloc(sizeof(int)); free(p); free(p); // 错误常见原因多个模块对同一资源的所有权和释放责任不清晰。6. Use After Return函数返回后使用栈内存函数返回后仍然访问该函数栈帧中的局部对象。是否检测到取决于编译器、运行时和相关配置。7. Memory Leak内存泄漏动态申请的内存不再使用却没有释放。在支持 LeakSanitizer 的平台上ASan 通常可以配合泄漏检测功能发现此类问题。是否可用取决于平台和运行时支持。三、ASan 的工作原理1. 编译器插桩编译时使用-fsanitizeaddress。编译器会在内存访问等位置插入额外检查代码。2. 运行时库ASan Runtime程序运行时配合插桩代码执行检查。发现非法访问时输出错误报告通常终止程序。3. Shadow Memory影子内存ASan 使用额外的影子内存记录应用内存区域的可访问状态。程序访问内存时插桩代码查询相应状态判断访问是否合法。可以把它理解为为程序内存维护一份辅助的状态记录。4. 性能影响ASan 会增加内存占用和运行时间。常见资料中提到的运行时间开销约为 2 倍但实际开销与程序和平台有关。通常用于开发、测试和问题定位不应未经评估就用于正式生产版本。四、GCC / G 中如何使用 ASan1. C 程序编译gcc -g -O1 -fsanitizeaddress -fno-omit-frame-pointer test.c -o test2. C 程序编译g -g -O1 -fsanitizeaddress -fno-omit-frame-pointer test.cpp -o test3. 运行./test4. 常用参数说明-g生成调试信息便于定位源代码行号。-O1使用较低级别优化兼顾运行表现和调试定位。-fsanitizeaddress启用 AddressSanitizer。-fno-omit-frame-pointer保留帧指针有助于生成更清晰的调用栈。5. 重要编译阶段和最终链接阶段都要带上-fsanitizeaddress。多文件工程应确保相关目标文件按一致的方式启用 ASan。运行时需要能够找到匹配的 ASan Runtime。五、CMake 工程中启用 ASan可以在 CMakeLists.txt 中添加cmake_minimum_required(VERSION 3.10) project(MyProject) set(CMAKE_CXX_STANDARD 11) add_compile_options( -g -O1 -fsanitizeaddress -fno-omit-frame-pointer ) add_link_options( -fsanitizeaddress ) add_executable(app main.cpp network.cpp video.cpp )构建和运行mkdir build cd build cmake .. cmake --build . ./app说明add_compile_options用于添加编译选项。add_link_options用于添加链接选项。如果只想对某个目标启用可以使用target_compile_options()和target_link_options()。add_link_options()需要较新的 CMake 版本旧版本可使用目标级链接选项等方式配置。六、如何阅读 ASan 错误报告常见报告关键字heap-buffer-overflow堆内存越界。stack-buffer-overflow栈内存越界。global-buffer-overflow全局变量内存越界。heap-use-after-free访问已经释放的堆内存。attempting double-free重复释放同一块内存。阅读报告时重点关注ERROR错误类型。READ / WRITE非法读取还是非法写入。at ... file.c:行号错误访问发生的位置。allocated by内存最初申请的位置。freed by内存释放的位置。thread T0 / T1发生问题的线程信息。排查思路先确认错误类型。找到报告中的源代码行号。检查出错地址对应的内存对象及其边界。如果涉及动态内存继续查看分配和释放位置。沿调用栈检查资源所有权、生命周期和并发访问逻辑。修复后重新编译并运行确认报告消失并补充回归测试。七、ASan 在嵌入式 Linux 项目中的用途1. TCP 网络通信检查接收缓冲区长度计算错误。检查数据拷贝时是否超出缓冲区边界。2. 视频流与图像处理检查视频帧缓存越界。检查帧缓冲区释放后仍被其他模块访问。检查图像尺寸、步长和内存长度计算错误。3. 多线程程序检查线程访问已经释放的对象。检查队列节点、任务对象等资源的生命周期问题。注意ASan 不是专门的数据竞争检测工具数据竞争通常使用 TSan。4. 链表、队列和缓存管理检查删除节点后继续访问。检查重复释放节点。检查缓冲区读写越界。5. 动态内存管理检查申请后未释放的内存需要平台支持泄漏检测。帮助定位内存对象的分配和释放位置。八、交叉编译和开发板上的注意事项在 i.MX6ULL、RK3568 等嵌入式 Linux 平台上使用 ASan需要同时满足交叉编译器支持-fsanitizeaddress。目标架构有匹配的 ASan 运行时库。目标根文件系统中包含运行时所需的库及依赖。程序能够在开发板上正确加载这些库。编译器、运行时库和目标系统的架构及 ABI 必须匹配。注意编译器接受-fsanitizeaddress不代表目标板一定能够运行程序。交叉编译时要检查工具链 sysroot 和开发板的根文件系统中有没有 ASan 的运行时库。建议先在 Ubuntu x86 Linux 上练习再研究目标板上的支持情况。嵌入式设备资源有限ASan 的额外内存和性能开销需要评估。九、相关工具对比1. GDB用途断点调试、单步执行、查看变量、调用栈和崩溃现场。2. ASanAddressSanitizer用途检测堆/栈/全局内存越界、释放后使用、重复释放等问题。3. TSanThreadSanitizer用途检测多线程数据竞争等线程同步问题。4. UBSanUndefinedBehaviorSanitizer用途检测部分未定义行为例如有符号整数溢出、非法移位、某些类型对齐问题等。5. Valgrind用途动态分析内存访问错误、内存泄漏等运行开销通常较大且需要考虑目标平台支持。十、建议掌握程度对于嵌入式 Linux C/C 应用开发建议掌握理解 ASan 的作用和基本工作原理。能区分堆越界、栈越界、Use After Free、Double Free。能使用 GCC / G 的-fsanitizeaddress编译程序。能在 CMake 工程中启用 ASan。能读懂 ASan 报告定位错误访问、内存申请和释放位置。了解 ASan 与 GDB、TSan、UBSan、Valgrind 的区别。了解交叉编译时 ASan Runtime 的依赖。建议动手练习编写一个堆内存越界程序。编写一个栈数组越界程序。编写一个 Use After Free 程序。编写一个 Double Free 程序。分别使用 ASan 编译运行观察报告并修复问题。一句话总结ASan 是一种通过编译器插桩和运行时检查来发现内存错误的工具。它能帮助开发者定位非法内存访问及相关的申请、释放位置是 C/C 程序开发和测试阶段非常实用的内存排错工具。
企业数字化 ERP 产品动态
相关推荐
《读懂 Token》README 越详细,AI 越看不懂:1000 Token 才是甜蜜点 README 越详细,AI 越看不懂:1000 Token 才是甜蜜点系列第 4 篇 实操层你花了一下午写给人类看的那份详细 README,AI 每次进你项目都得从头读一遍。
这句话听起来有点反直觉——README 不是越详细越好吗?对人类读者来说是的。但 A… · 2026/11/3 2:50:28
深入理解内存对齐:原理、优化与实践 1. 内存对齐的概念与必要性内存对齐是计算机系统中一个基础但极其重要的概念。简单来说,它指的是数据在内存中的存储位置必须满足特定边界要求。比如一个4字节的int型变量,在32位系统上通常需要从4的倍数地址开始存放。为什么需要内存对齐?这… · 2026/11/3 3:30:34
Delphi Web前端开发入门:用Pascal与TMS WEB Core做网页 简介:Delphi Web前端开发教程以TMS WEB Core框架为主线,面向希望用Delphi或Lazarus快速进入Web应用开发的初学者与进阶开发者,也适合传统Delphi程序员补齐前端与跨平台发布知识。教程从Delphi/Object Pascal的历史与现状讲起,梳理… · 2026/11/3 3:30:34
程序员转型大模型开发的系统化学习路径 1. 为什么程序员转型大模型需要系统化学习路径去年我在团队内部推动AI大模型落地时,发现一个有趣现象:有五年经验的Java工程师花两周速成Transformer原理后,在微调任务上的表现反而不如按部就班学习的新人。这个观察印证了标题强调的观点——… · 2026/11/3 3:30:34
基于Spark与深度学习的智能地铁客流预测系统 1. 项目背景与核心价值地铁客流量预测是智慧城市建设中的关键环节。作为一线城市交通管理的痛点,早晚高峰期的客流压力常常导致站台拥挤、列车延误等问题。传统基于人工经验或简单统计模型的预测方法,在面对突发天气、节假日、大型活动等复杂场景时往往表… · 2026/11/3 3:30:34
SpringBoot农产品管理APP开发实战与架构设计 1. 项目概述:农产品管理与销售APP的设计初衷去年帮农科院做数字化改造时,发现许多合作社还在用纸质台账管理进出货,农户的优质产品经常因信息不对称滞销。这个基于SpringBoot的农产品管理APP正是为解决这类痛点而生——通过移动端实现农产品从… · 2026/11/3 3:30:34
StatusServer:分布式系统健康监控的核心架构与实践 1. StatusServer:现代分布式系统的健康监控中枢在分布式架构成为主流的今天,服务健康监控已从"可有可无"变成了"生死攸关"的基础设施。三年前我们某个核心服务的一次雪崩事故让我深刻认识到:当30个微服务节点中有3个出现… · 2026/11/3 3:29:34
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 4:42:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 5:17:18