用gdb分析core文件可定位数组越界:先bt找用户函数帧,再frame切换、list看源码、print查索引与边界;需编译时加-g且禁用优化;AddressSanitizer才是开发期可靠检测手段。

直接用 gdb 加载 core 文件后执行 bt,再结合 frame 和 print 查看数组访问索引和边界——但前提是编译时加了 -g,且崩溃点能落到源码行(比如越界读写未被优化掉)。
确认崩溃是否由数组越界触发
不是所有数组访问问题都会立刻 crash;有些会破坏堆结构或覆盖相邻变量,延迟报错。真正“当场崩溃”的典型场景包括:
- 栈上大数组声明(如
int buf[1024*1024])导致栈溢出,信号通常是SIGSEGV或SIGABRT - 对
nullptr或已free/delete的指针做下标访问(如p[i]) - 访问
std::vector未检查边界的operator[](不抛异常,行为未定义) - 使用
malloc分配的内存,但索引超出size(无运行时检查)
如果 bt 显示崩溃在 memcpy、memset、std::string::_M_mutate 等内部函数里,大概率是底层缓冲区越界,需往上翻调用栈找原始数组操作点。
用 GDB 定位数组越界的具体索引和长度
进入 gdb ./a.out core 后,关键不是只看 bt,而是要钻进最顶层的用户函数帧:
立即学习“C++免费学习笔记(深入)”;
- 执行
bt找到最靠近你代码的栈帧(比如#2 0x00005555555551a9 in process_data () at main.cpp:23) - 执行
frame 2(数字替换成对应帧号),切换过去 - 执行
list看源码上下文,确认哪一行在读/写数组 - 执行
print i、print arr_size、print &arr[i]等,验证索引是否越界 - 若变量被优化掉(显示
<optimized out></optimized>),说明没加-g -O0或用了-O2以上;此时可尝试info registers看rdi/rsi寄存器值(常存地址/长度),再用x/10wx $rdi-16查内存布局
为什么有时候 bt 看不到数组访问行?
常见原因有三个:
-
g++默认开启-O1或更高优化等级,把数组访问内联或消除了中间变量,导致崩溃点落在汇编指令级,源码映射丢失 - 崩溃发生在
libc内部(如strcpy检测到重叠或越界后主动 abort),这时bt顶帧是__libc_message,得用up往上调用栈,直到看到你自己的函数 - 程序用了
setjmp/longjmp或 signal handler 覆盖了默认SIGSEGV行为,导致 core 不包含完整上下文——这种情况下core可能根本没记录崩溃前的栈,得改用backtrace()+addr2line在代码里埋点
真正可靠的数组越界检测,不能只靠 core dump:开发期务必启用 AddressSanitizer(g++ -fsanitize=address -g),它能在越界发生瞬间打印出精确文件、行号、访问类型(read/write)、对象大小和实际偏移。


















