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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:35:21