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

C++归并排序算法异常行为求助:莫名出现值16

排查归并排序中的奇怪随机值bug

嘿,我一眼就揪出你代码里的问题了——这是数组越界访问导致的栈内存污染,那些莫名其妙的16就是栈里的垃圾数据被错误读出来了!

问题根源分析

你在merge函数里的第二个判断条件完全搞错了维度:

else if (s2 > r)

s2是辅助数组aux的索引,而r是原数组的右边界,两者根本不是一个体系的!aux数组的长度是r-l+1,它的有效索引范围是0到r-l(因为数组从0开始计数)。你初始的s2是(r-l)/2 +1,这是aux右半部分的起始索引,所以判断s2是否越界应该是s2 > (r-l),而不是s2>r。

当你用错误的条件时,这个判断几乎永远不会触发,程序会不断从aux的越界位置读取数据。而aux是栈上的变长数组(VLA),越界访问会直接踩到栈里的其他垃圾值——那些16就是这么来的。

为什么加输出就正常?

这纯属巧合!当你在merge里加cout输出时,栈的内存布局被改变了,越界访问到的位置刚好是合法的数据,或者输出操作触发了栈的清理/对齐,暂时掩盖了问题,但bug本身并没有被修复。

修复后的代码

我把错误的判断条件修正了,还做了一些代码可读性优化:

#include <bits/stdc++.h>
using namespace std;

int merge(int *ar, int l, int r) {
    int len = r - l + 1;
    // 用vector代替VLA,符合C++标准,更安全
    vector<int> aux(len);
    int s1 = 0, s2 = len / 2;
    for (int i = 0; i < len; i++)
        aux[i] = ar[l + i];
    for (int k = 0; k < len; k++) {
        // 左半部分已取完:s1到达左半部分的最后一个索引
        if (s1 >= len/2)
            ar[l + k] = aux[s2++];
        // 右半部分已取完:s2超出aux的有效范围
        else if (s2 >= len)
            ar[l + k] = aux[s1++];
        else if (aux[s1] <= aux[s2])
            ar[l + k] = aux[s1++];
        else
            ar[l + k] = aux[s2++];
    }
    return 0;
}

void mergesort(int *ar, int l, int r) {
    if (l >= r) return;
    int mid = (l + r) / 2;
    mergesort(ar, l, mid);
    mergesort(ar, mid + 1, r);
    merge(ar, l, r);
}

int main() {
    int ar[] ={ 34, 54, 56, 42, 32, 46, 99, 85, 5, 45, 34, 54, 6, 56, 54, 64, 5 };
    int l = 0, r = sizeof(ar) / sizeof(int) - 1;
    mergesort(ar, l, r);
    for (int i = 0; i < r + 1; i++)
        cout << ar[i] << " ";
    return 0;
}

额外优化说明

  • 把r-l+1提取成变量len,避免重复计算,代码更清晰。
  • 用vector<int>代替栈上的变长数组(VLA):C++标准并不支持VLA,这是GCC的扩展特性,用vector更符合标准,还能避免大数组导致的栈溢出问题。
  • 调整了左右半部分的结束判断逻辑,直接基于len计算,更直观不易出错。

运行修复后的代码,就能得到正确的排序结果啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 19:47:30