C++代码触发AddressSanitizer栈缓冲区下溢错误,请求排查原因
栈缓冲区下溢错误分析与修复
问题代码
bool check(vector<int> &nums) { int *big = &nums[0]; int n = nums.size(), x = 0; for (int i = n - 2; i > -1; i--) { if (nums[i] > x) { x = nums[i]; } } big = &x; if (big != &nums[n - 1]) { big++; } rotate(&nums[0], big, &nums[n]); for (int i = 1; i < n; i++) { if (nums[i - 1] > nums[i]) return false; } return true; }
错误信息
ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7ffd698133fc at pc 0x00000034d07d bp 0x7ffd69813370 sp 0x7ffd69813368
错误原因
核心问题是**big被赋值为栈局部变量x的地址**,而std::rotate要求传入的三个指针(迭代器)必须属于同一个容器的连续内存范围。x是函数栈上的变量,和nums的动态数组内存完全无关。
当执行big != &nums[n - 1]时,这个比较毫无意义(两个指针指向不同内存区域),随后执行big++会让big指向x之后的栈内存地址,属于非法的越界访问,直接触发栈缓冲区下溢错误。
此外,原代码逻辑错误:只记录了最大值的数值,却丢失了该值在nums中的位置,导致后续rotate操作完全偏离预期。
修复方案
修改逻辑,记录最大值在nums中的索引,确保big始终指向nums容器内的元素,保证rotate的参数合法:
bool check(vector<int> &nums) { int n = nums.size(); if (n <= 1) return true; // 处理空容器或单个元素的边界情况 int max_val = nums[0]; int max_idx = 0; // 从倒数第二个元素向前遍历,找到最大值的位置 for (int i = n - 2; i >= 0; i--) { if (nums[i] > max_val) { max_val = nums[i]; max_idx = i; } } int* big = &nums[max_idx]; if (big != &nums[n - 1]) { big++; } rotate(&nums[0], big, &nums[n]); // 检查旋转后的数组是否非递减 for (int i = 1; i < n; i++) { if (nums[i - 1] > nums[i]) return false; } return true; }
修复要点
- 不再使用栈变量的地址,而是通过索引定位
nums内的最大值元素,确保big指向合法的容器内存 - 增加边界处理,避免空容器或单个元素时的无效遍历
- 保证
rotate的三个指针都处于nums的内存范围内,彻底消除越界访问
内容的提问来源于stack exchange,提问作者HARSH PRANJAL
相关产品推荐
相关产品推荐

