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

函数局部变量validTugboatCount出现随机异常行为求助

拖船排序函数中变量值异常的排查与解决

问题描述

编写程序计算拖船与主船的距离并按远近排序,同时移除位置无效的拖船时,sortTugboats函数内的局部变量validTugboatCount出现异常:

  • 循环统计有效拖船数后,变量值正确(例如4);
  • 调用mergeSort后,变量值变为随机垃圾值;
  • 在循环后添加printf输出该变量,值又能保持正确。
    尝试统一使用long long int参数后问题仍存在,需排查根本原因。

相关代码片段

初始代码

void sortTugboats(tugboat * unsorted, long long int tugboatCount){
    long long int validTugboatCount = 0;
    for(int i = 0; i < tugboatCount; i++){
        if(!unsorted[i].isInvalid)
            validTugboatCount++;
    } // validTugboatCount 此时值正确,比如4

    tugboat validUnsorteds[validTugboatCount]; // 数组大小为4

    for(int i = 0; i < tugboatCount; i++){
        if(!unsorted[i].isInvalid)
            validUnsorteds[i] = unsorted[i];
    }

    mergeSort(validUnsorteds, 0, validTugboatCount-1); // 此处validTugboatCount变为随机值,比如140733193388031

    unsorted = validUnsorteds;
}

添加printf后的代码

void sortTugboats(tugboat * unsorted, long long int tugboatCount){
    long long int validTugboatCount = 0;
    for(int i = 0; i < tugboatCount; i++){
        if(!unsorted[i].isInvalid)
            validTugboatCount++;
    } // validTugboatCount 此时值正确,比如4

    printf("%lld\n", validTugboatCount); // 输出4

    tugboat validUnsorteds[validTugboatCount]; // 数组大小为4

    for(int i = 0; i < tugboatCount; i++){
        if(!unsorted[i].isInvalid)
            validUnsorteds[i] = unsorted[i];
    }

    mergeSort(validUnsorteds, 0, validTugboatCount-1); // validTugboatCount 值保持4
}

问题根源分析

  1. 数组越界写入破坏栈内存
    第二个循环遍历的是所有拖船数tugboatCount,但validUnsorteds数组的大小是有效拖船数validTugboatCount(必然小于等于tugboatCount)。当i超过validTugboatCount-1时,对validUnsorteds[i]的赋值会越界,直接覆盖栈上的其他变量内存(恰好是validTugboatCount的存储位置),导致其值被篡改。

  2. printf的“伪修复”原理
    添加printf后,栈的布局被改变:printf的调用会在栈上分配额外空间,使得越界写入的位置不再覆盖validTugboatCount的内存。这只是巧合掩盖了问题,并未真正修复数组越界的根本错误。

  3. 额外问题:局部数组无法传递到外部
    unsorted = validUnsorteds;仅修改了函数内的局部指针,不会影响外部传入的指针。且validUnsorteds是栈上的局部数组,函数结束后会被销毁,外部无法安全访问该数组内容。

修复方案

1. 修正数组填充逻辑

使用独立的索引变量填充有效拖船数组,避免越界:

int idx = 0;
for(int i = 0; i < tugboatCount; i++){
    if(!unsorted[i].isInvalid)
        validUnsorteds[idx++] = unsorted[i];
}

2. 改用动态内存分配

栈上的变长数组(VLA)存在大小限制且函数结束后销毁,改用堆内存分配解决内存生命周期问题:

tugboat* sortTugboats(tugboat * unsorted, long long int tugboatCount){
    long long int validTugboatCount = 0;
    for(int i = 0; i < tugboatCount; i++){
        if(!unsorted[i].isInvalid)
            validTugboatCount++;
    }

    // 动态分配内存
    tugboat* validUnsorteds = malloc(sizeof(tugboat) * validTugboatCount);
    if(!validUnsorteds) return NULL; // 处理内存分配失败情况

    int idx = 0;
    for(int i = 0; i < tugboatCount; i++){
        if(!unsorted[i].isInvalid)
            validUnsorteds[idx++] = unsorted[i];
    }

    mergeSort(validUnsorteds, 0, validTugboatCount-1);

    return validUnsorteds; // 返回动态分配的数组,外部调用者需负责用free释放内存
}

3. 检查mergeSort实现

确保mergeSort内部没有数组越界访问的逻辑,避免进一步破坏栈内存。

内容的提问来源于stack exchange,提问作者C͝͡e̷͢pt̡̕i̴̸͘u͜͠͝m

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:35:44