You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解读C++ g++环境下AddressSanitizer输出的报错日志

AddressSanitizer 日志阅读方法&问题定位

ASan的日志结构非常固定,按顺序读四个部分就行,不用全啃完,大部分时候看前三个部分就能定位问题。


1. 先读顶部错误概要

第一行直接给核心结论:

  • 错误类型:你这次的是heap-buffer-overflow,即堆缓冲区越界访问,其他常见类型还有stack-buffer-overflow(栈越界)、use-after-free(使用已释放内存)、double-free(重复释放)、memory-leak(内存泄漏)
  • 访问类型:第二行写的READ of size 242,说明是读操作越界,总共尝试读242字节
  • 出错地址:就是后面跟着的内存地址,后续内存块信息会对应这个地址

2. 读第一组调用栈:找错误触发点

这组栈是越界发生瞬间的调用链,从最底层的报错函数往上数,直接跳过ASan自身的函数、C++标准库内部函数、系统加载器函数,只找你自己写的代码文件对应的帧:

  • 你这次的栈里,#0是ASan拦截的strlen函数,#1~#3是标准库std::string的构造逻辑,到#4就到了你自己的代码:cinc::base::string::operator std::string() string.h:656,再往上#5是main函数string.cpp:153
  • 到这里就能得到直接触发原因:你在自定义string转std::string的运算符重载里,传给std::string构造函数的char有问题,导致内部strlen读内存的时候越界了——strlen是靠找'\0'判断字符串结尾的,出现这个错误基本就是传进去的char没有正确的'\0'终止符。

3. 读第二组调用栈:找出问题的内存来源

报错概要下面会明确写出错内存和对应堆块的关系,紧接着是这块堆块的分配调用链,同样跳过系统、ASan、标准库的帧,找你自己的代码:

  • 你这次的日志明确写了:0x611000000271 is located 0 bytes to the right of 241-byte region [0x611000000180,0x611000000271),翻译过来就是:你越界访问的地址,刚好紧挨着一块你分配的241字节堆内存的尾部,差0字节就到边界,属于典型的off-by-one(差一)错误。
  • 对应的分配栈里,#1是你写的alloc<char>函数(global.h:31),#2是strduplc函数(string.h:36),#3是自定义string的operator+重载(string.h:673),同样是被main函数153行调用的。
  • 结合前面的读242字节的信息,问题已经很明确了:你在operator+里拼接字符串时,分配了241字节的内存存拼接结果,但是C风格字符串要求末尾多1字节存'\0',你要么是分配大小的时候没算这1字节,要么是拷贝完字符后忘了在末尾补'\0',导致strlen顺着内存往后读,读完241字节的有效内容还没碰到终止符,继续往后读1字节就撞到了堆块的边界红区,触发ASan报错。

4. 影子内存部分(可选)

这部分是ASan对内存状态的标记,你日志里箭头指向的[01]fa,对照下面的图例:01代表这组8字节里只有前1字节可访问,fa是堆边界的不可访问红区,刚好对应你越界读了堆块外第一字节的情况,和前面的结论完全吻合。这部分一般不用特意研究,前面三部分信息不够的时候再对照图例查就行。


针对你这次问题的排查点

直接去对应行查代码就行,不用瞎回滚:

  • 查string.h:673的operator+实现:计算拼接后内存大小的时候,是不是只加了两个字符串的长度,没额外+1给'\0'留位置
  • 查string.h:36的strduplc实现:拷贝完所有字符后,有没有手动在最后一位写入'\0'
  • 查string.h:656的类型转换运算符:如果你的自定义string本身存了长度信息,转std::string的时候可以直接用std::string(内部指针, 长度)的构造重载,绕过strlen的逻辑,从根源上避免因为缺终止符导致的越界。

日常排查小技巧

  • 编译带ASan的版本时不要开-O2优化,用-Og -g就够,优化等级太高会导致栈内行号、函数信息错位,你之前加这两个参数的操作是对的
  • 所有调用栈里,只要文件名不是你自己写的、不是你项目里的,直接跳过,不用浪费时间看,能把栈的阅读时间压缩到几秒
  • 手动写内存分配、C风格字符串操作的时候,只要碰到strlen、strcpy这类函数报越界,优先查'\0'的问题,90%的情况都是漏了终止符。

内容的提问来源于stack exchange,提问作者user3134709

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:30:36