C 康威';s的生命缓冲下溢游戏

C 康威';s的生命缓冲下溢游戏,c,conways-game-of-life,stackunderflow,C,Conways Game Of Life,Stackunderflow,我是C语言的新手,以前听说过缓冲区溢出,但从未听说过堆栈缓冲区下溢。我一直在努力阅读,从我的理解来看,我分配了太多的内存?我只是想确保我正确理解这个问题。因此,我的问题与以下代码有关,这些代码需要几代人才能更新康威《生命游戏》的给定文件。如果有人能解释我在哪里误解了什么,我将非常感激。输入应遵循“/life.c#board.txt”的行,其中#是代数,board.txt是由“.”和“*”构成的板。board.txt的第一行还包含行数和列数。奇怪的是,该代码有时适用于较小的电路板,但会为较大的电路

我是C语言的新手,以前听说过缓冲区溢出,但从未听说过堆栈缓冲区下溢。我一直在努力阅读,从我的理解来看,我分配了太多的内存?我只是想确保我正确理解这个问题。因此,我的问题与以下代码有关,这些代码需要几代人才能更新康威《生命游戏》的给定文件。如果有人能解释我在哪里误解了什么,我将非常感激。输入应遵循“/life.c#board.txt”的行,其中#是代数,board.txt是由“.”和“*”构成的板。board.txt的第一行还包含行数和列数。奇怪的是,该代码有时适用于较小的电路板,但会为较大的电路板创建缓冲区下溢

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

void futureGens(int numRows, int numCols, int original[numRows][numCols], int generations){
    int future[numRows][numCols];
    int i, j;

    for(i = 0; i < numRows; i++){
        for(j = 0; j < numCols; j++){
            int live = 0;

            if(original[i-1][j-1] == 1){
                live++;
            }
            if(original[i-1][j] == 1){
                live++;
            }
            if(original[i-1][j+1] == 1){
                live++;
            }
            if(original[i][j-1] == 1){
                live++;
            }
            if(original[i][j] == 1){
                live++;
            }
            if(original[i][j+1] == 1){
                live++;
            }
            if(original[i+1][j-1] == 1){
                live++;
            }   
            if(original[i+1][j] == 1){
                live++;
            }
            if(original[i+1][j+1] == 1){
                live++;
            }

            live -= original[i][j];

            switch(live){
                case 0:
                case 1: 
                    future[i][j] = 0;
                    break;
                case 2:
                    future[i][j] = original[i][j];
                    break;
                case 3:
                    future[i][j] = 1;
                    break;
                default:
                    future[i][j] = 0;
            }   
        }
    }

    if(generations == 1){           
        //printf("\nFuture: \n");
        for(i = 0; i < numRows; i++){
            for(j = 0; j < numCols; j++){
                if(future[i][j] == 1){
                    printf("*");
                } else {
                    printf(".");
                } 

                //printf("%d", future[i][j]);
            }
            printf("\n");
        }
    }   
     else {
        futureGens(numRows, numCols, future, generations-1);
    } 
}

int main(int argc, char **argv){
    if(argc != 3) {
        return EXIT_FAILURE;
    }

    int generations = atoi(argv[1]);

    FILE *fp = fopen(argv[2], "r");
    if(fp == NULL){
        printf("error: nothing in file\n");
        return EXIT_FAILURE;
    }

    int numRows = 0, numCols = 0;
    char line[256];

    if(fgets(line, sizeof(line), fp)){
        char c[256];
        int p;

        for(p = 0; p < 256; p++){
            if(isdigit(line[p]) != 0){
                c[p] = line[p];
            } else {
                break;
            }

        }

        numRows = atoi(c);
        numCols = atoi(c);
        printf("row: %d, col: %d\n", numRows, numCols);
    }

    //initialize the original array
    int original[numRows][numCols];
    int i, j;

    for(i = 0; i < numRows; i++){
        fgets(line, sizeof(line), fp);
        for(j = 0; j < numCols; j++){
            char c = line[j];
            if(c == '.'){
                original[i][j] = 0;
            } else if(c == '*'){
                original[i][j] = 1;
            }
        }   
    }

    futureGens(numRows, numCols, original, generations);

    return EXIT_SUCCESS;
}
#包括
#包括
#包括
#包括
虚无的未来(int numRows,int numCols,int original[numRows][numCols],int generations){
int future[numRows][numCols];
int i,j;
对于(i=0;i
i
j
为零时,则
original[i-1][j-1]
尝试访问数组
original
之外的元素

C标准没有定义结果行为。在许多C实现中,这通常会尝试访问阵列外部的内存。数组行越大(列越多),数组
原始[i-1]
的外部越远,尝试访问未映射内存的可能性越大,这将导致故障

必须编写不访问数组外部元素的代码

对于必须检查数组元素邻居的算法,有几种常见的方法:

  • 在考虑每个元素时,使用
    if
    语句测试它在数组中是否有邻居。对于邻居不存在的任何方向,不要尝试检查那里的元素。此代码导致对每个元素重复测试数组边界
  • 将数组的处理分离为内部元素的主循环(或一组嵌套循环,每个维度一个),所有这些元素在所有方向上都有邻居,并且数组的边(例如“左”方向)有单独的循环边,其中
    i
    为零,元素在左边没有邻居。因此,不需要对每个元素进行单独测试;每个循环处理在该循环中处理的元素的邻居已知的情况。角点也必须单独处理
  • 在包含中性信息的边缘用虚拟行和列填充数组。因此,对于所需的数组大小
    R
    行和
    C
    列,将使用实际数组大小
    R+2
    行和
    C+2
    列。处理元素的循环将遍历行1到
    R-2
    列粗列1至
    C-2
    • i