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

森林火灾模拟程序修改行数后rows/colm出现超大随机数求助

森林火灾模拟程序行数修改后的数据异常排查

将测试配置从9行20列改为8行20列后,程序输出的rows和colm变为超大随机数,原配置运行正常。以下是相关代码、输入文件及异常输出:

相关代码

#include <stdio.h>

void InfoInput(int *rows, int *colm, int *seed, int *fireProb){
    FILE *file;
    char line[256];
    file = fopen("Test.txt", "r");
    if (file ==NULL){
        printf("fatal error\n");
    }
    
    fscanf(file, "%d",rows);
    fscanf(file, "%d",colm);
    fscanf(file, "%d",seed);
    fscanf(file, "%d",fireProb);
}

void treeInput(char forest[][102], int rows, int colm, int *totTrees){
    FILE *file;
    char line[256];
    file = fopen("Test.txt", "r");
    if (file ==NULL){
        printf("fatal error\n");
    }
    
    char temp;
    int x=0, tempRow, tempColm;
    while(x<100){
        fscanf(file, " %c", &temp);
        if(temp == 'Q'){
            x=1;
            break;
        } else if(temp == 'A'){
            for(int i = 0; i<rows; i++){
                for(int j = 0; j<colm; j++){
                    forest[i][j] = 'T';
                }
            }
        } else if (temp == 'T'||temp == 'E'||temp == 'F'){
            fscanf(file, "%d", &tempRow);
            fscanf(file, "%d", &tempColm);
            if(temp == 'T'){
                forest[tempRow-1][tempColm-1] = 'T';
            } if(temp == 'F'){
                forest[tempRow-1][tempColm-1] = 'F';
            }
            else {
                forest[tempRow-1][tempColm-1] = '.';
            }
        }
    }
    for(int i = 0; i<rows; i++){
        for(int j = 0; j<colm; j++){
            if (forest[i][j] == 'T'){
                *totTrees += 1;
            }
        }
    }
   
}

void printInfo(char forest[][102], int rows, int colm, int seed, int fireProb, int totTrees){
    printf("S. Madden 9/20\n\n");
    printf("rows: %d\n", rows);
    printf("cols: %d\n", colm);
    printf("trees: %d\n",totTrees);
    printf("seed: %d\n", seed);
    printf("probability: %d%%\n\n",fireProb);
   
}


int main()
{
    FILE *file;
    char line[256];
    file = fopen("Test.txt", "r");
    if (file ==NULL){
        printf("fatal error\n");
    }
    
    int rows, colm, seed, fireProb, Time=0;
    int totTrees = 0;
    
    InfoInput(&rows, &colm, &seed, &fireProb);
    //manualInput(&rows, &colm, &seed, &fireProb);
    
    char forest[rows][colm];
    
    treeInput(forest, rows, colm, &totTrees);
    
    printInfo(forest, rows, colm, seed, fireProb, totTrees);

    return 0;
}

输入文件Test.txt内容

8
20
28
75
A
F 3 4
E 1 12
E 2 12
E 3 12
E 4 12
E 4 13
E 4 14
E 5 12
E 5 15
E 6 12
E 1 16
E 2 16
E 3 16
E 4 16
E 7 1
E 7 2
E 7 3
E 7 4
E 8 3
Q

异常输出

S. Madden 9/20

rows: 777278548
cols: 1414812756
trees: 141
seed: 28
probability: 75%

问题根源

  • 栈内存越界破坏变量:main中声明的char forest[rows][colm]是变长数组(VLA),存储在栈上。但treeInput函数的参数声明为char forest[][102],函数内部会按照102列的步长计算数组元素的内存地址。当实际传入的数组列数是20时,访问forest[i][j]会超出数组实际占用的内存范围,导致栈上的相邻变量被覆盖。
  • 9行20列时,栈布局刚好没让越界写入覆盖到rows和colm;改为8行后,栈上变量的相对位置变化,越界写入直接破坏了rows和colm的内存值,所以输出随机超大数。
  • 额外问题:treeInput中if(temp == 'T')后未加else就写if(temp == 'F'),存在逻辑漏洞,可能导致错误赋值。

修复方案

1. 统一数组维度声明

将treeInput的参数改为接受变长数组,匹配实际传入的数组维度,避免越界计算:

// 调整参数顺序,先传入rows和colm,再传入数组
void treeInput(int rows, int colm, char forest[rows][colm], int *totTrees)

2. 优化文件操作

避免重复打开文件,改为在main中打开一次,通过文件指针传递给函数,读完信息后重新定位指针:

// 修改InfoInput,接收已打开的文件指针
void InfoInput(FILE *file, int *rows, int *colm, int *seed, int *fireProb){
    fscanf(file, "%d", rows);
    fscanf(file, "%d", colm);
    fscanf(file, "%d", seed);
    fscanf(file, "%d", fireProb);
}

// 在treeInput中重新定位到文件开头,跳过前四个整数
void treeInput(int rows, int colm, char forest[rows][colm], int *totTrees, FILE *file){
    fseek(file, 0, SEEK_SET);
    int skip;
    for(int i=0; i<4; i++){
        fscanf(file, "%d", &skip);
    }
    // 后续原有逻辑...
}

3. 修复逻辑漏洞

将treeInput中的条件判断改为else if,避免重复判断:

if(temp == 'T'){
    forest[tempRow-1][tempColm-1] = 'T';
} else if(temp == 'F'){
    forest[tempRow-1][tempColm-1] = 'F';
} else {
    forest[tempRow-1][tempColm-1] = '.';
}

4. 添加错误处理

fopen失败时直接终止程序,避免后续非法操作:

#include <stdlib.h> // 引入exit函数

int main(){
    FILE *file = fopen("Test.txt", "r");
    if(file == NULL){
        printf("fatal error\n");
        exit(1); // 终止程序
    }
    // 后续逻辑...
    fclose(file); // 关闭文件
    return 0;
}

内容的提问来源于stack exchange,提问作者Sarah Madden

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:35:57