用C二维数组的指针访问,分段故障 [英] 2D array pointer access segmentation fault in C

查看:92
本文介绍了用C二维数组的指针访问,分段故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图写一个康威在C.生命游戏一个code我有包含我的宇宙一些问题二维数组。我会告诉你,导致我一个问题,code的部分。其实有两个问题,我不能处理的。

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括file2ppm.h的typedef枚举{假的,真正的布尔};无效* allocateMemoryFor2DArray(INT X,int y)对; //分配内存的二维数组
无效initializeUniverseFromFile(字符*路径,诠释的x,INT Y,int数组[X] [Y]); //从文件单元的设定值
无效initializeUniverseRandomly(INT X,INT Y,int数组[X] [Y]); //设置随机值
INT getNumberOfColumns(FILE *文件); //获取文件列数(宇宙yDim)
诠释getNumberOfLines(FILE *文件); //获取文件的行数(宇宙xDim)
无效print2DArray(INT X,INT Y,int数组[X] [Y]); //打印二维数组
无效setDimensionsFromFile(字符*路径,诠释* xDim,为int * yDim,为int * xDimB,为int * yDimB); //设置宇宙的尺寸INT主(INT ARGC,CHAR *的argv [])
{
    INT I,J,N; //循环指标
    INT n步; //世代数
    INT IM,IP,JM,JP; //邻居的边界
    INT yDim,xDim;由用户(生活区)//定义宇宙boundarier;
    INT xDimB,yDimB; //宇宙的边界由1扩大到每侧
    INT nsum,ISUM; //邻居的总和,迭代后活细胞的总和
    // ** INT老,**新; //宇宙
    INT(*旧)[xDimB]; //宇宙
    INT(*新)[xDimB]; //宇宙    浮X; //随机化第一人口
    字符* inputPath; //路径与ixDimBtial uxDimBverse文件
    字符* outputPath; //路径输出PPM文件
    //临时副本
    INT yDim_copy,xDim_copy;    的printf(ARGC数:%d \\ n,ARGC);
    开关(ARGC){
        案例4://从文件中读取最初的宇宙
            //带参数
            n步=的atoi(ARGV [1]); //获取迭代次数
            outputPath =的argv [2]; //获取outputimages路径
            inputPath = argv的[3]; //文件与初始化uxDimBverse;
            setDimensionsFromFile(inputPath,&安培; xDim,&安培; yDim,&安培; xDimB,&安培; yDimB);
            老= allocateMemoryFor2DArray(xDimB,yDimB); // Alocate内存扩展宇宙
            新= allocateMemoryFor2DArray(xDimB,yDimB);
            的printf(初始化之前:yDim:%D,xDim数:%d \\ n,yDim,xDim); //这里的值都不错
            // tmp目录拷贝
            yDim_copy = yDim;
            xDim_copy = xDim;
            initializeUniverseFromFile(inputPath,xDim,yDim,老);
            的printf(后初始化:yDim:%D,xDim数:%d \\ n,yDim,xDim); //这里人们朦胧改变
            yDim = yDim_copy; //我拿了一份避免这个问题,现在
            xDim = xDim_copy;            的printf(从副本服用后​​:yDim:%D,xDim数:%d \\ n,yDim,xDim); //这里的尺寸是很好的再次
            的memcpy(新,老,xDimB * yDimB * sizeof的(旧[xDimB] [yDimB])); //复制旧到新
            打破;
        默认:
            的printf(用法:%s的iter_number,output_name中,yDim,xDim \\ N的argv [0]);
            的printf(或\\ n);
            的printf(用法:%s的iter_number,output_name中,ixDimBtial_input_name \\ N的argv [0]);
            的printf(注:初始文件必须在./data/\
);
            返回1;
    }    print2DArray(xDim,yDim,老); //这工作正常
    的printf(在主:yDim:%D,xDim数:%d \\ n,yDim,xDim);
    的printf(%d个\\ N,老[0] [0]); //这工作正常
    的printf(%d个\\ N,老[2] [2]); //分割失败    返回0;
}无效* allocateMemoryFor2DArray(INT X,int y)对{
    INT(*数组)[Y] =的malloc(sizeof的(INT [X] [Y])); //分配内存
    如果(阵列== NULL){/ *经常检查的malloc *返回/
        PERROR(malloc的);
        出口(EXIT_FAILURE);
    }
    返回数组;
}INT getNumberOfColumns(FILE *文件){
    INT yDim = 0;
    焦炭CH;    做
    {
        CH = GETC(文件); //从文件1字符        如果(CH =='\\ n')//如果Ch是新生产线
        {
            倒带(文件); //移动文件指针到文件的beginxDimBng
            返回yDim; //发现数列
        }
        其他
            ++ yDim;    }而(CH = EOF!);
}INT getNumberOfLines(FILE *文件){
    INT xDim = 0;
    焦炭CH;    做
    {
        CH = GETC(文件); //从文件1字符
        如果(CH =='\\ n')//如果新行
        {
            ++ xDim; //增加xDim(另一行)
        }
    }而(CH = EOF!);
    倒带(文件); //移动文件指针到文件的beginxDimBng
    返回xDim;
}
无效print2DArray(INT X,INT Y,int数组[X] [Y])
{
    INT I,J;
    的printf(X:%D,Y数:%d \\ n,X,Y);
    对于(i = 1; I< = X ++ I)
    {
        为(J = 1; J< = Y ++ j)条
        {
            的printf(%d个,数组[I] [J]);
        }
        的printf(\\ n);
    }
}无效setDimensionsFromFile(字符*路径,诠释* xDim,为int * yDim,为int * xDimB,为int * yDimB)
{
    FILE *文件;
    INT I,J;
    文件= FOPEN(路径,R); //打开文件
    如果(文件)
    {
        * yDim = getNumberOfColumns(文件);
        * xDim = getNumberOfLines(文件);
        * xDimB = * xDim + 2; //添加2为左和右环面拓扑
        * yDimB = * yDim + 2;
        如果(* xDim大于0&放大器;&放大器; * yDim大于0)
        {
            的printf(UxDimBverse尺寸%深x%d个\\ N,* xDim,* yDim);
        }
        其他
        {
            PERROR(错误初始化文件);
            出口(EXIT_FAILURE);
        }        FCLOSE(文件); //关闭文件
    }
    其他
    {
        PERROR(打开初始化文件错误);
        出口(EXIT_FAILURE);
    }
}
无效initializeUniverseFromFile(字符*路径,诠释的x,INT Y,int数组[X] [Y])
{
    FILE *文件;
    INT I,J;
    文件= FOPEN(路径,R); //打开文件
    如果(文件)
    {
        // IxDimBtialize阵列
        字符* CH;
        对于(i = 1; I< = X,我++)
        {
            //输出(I:%D,我);
            为(J = 1; J< = Y; J ++)
            {
                //的printf(歼数:%d,J);
                如果(的fscanf(文件%C,CH)!= 1)
                {
                    PERROR(读取错误。\\ n);
                }
                否则,如果(ISDIGIT((无符号字符)* CH))
                {
                    的printf(%D,与atoi(CH));
                    数组[I] [J] =的atoi(CH);
                }
                其他
                {
                    //输出(NUMER znaku数:%d,CH);
                    j--;
                }
            }
            的printf(\\ n);
        }
        的printf(读完\\ n);
        FCLOSE(文件); //关闭文件
    }
    其他
    {//文件打开错误
        PERROR(打开初始化文件错误);
        出口(EXIT_FAILURE);
    }
    的printf(在初始化yDim:%D,xDim数:%d \\ n,X,Y);
}无效initializeUniverseRandomly(INT X,INT Y,int数组[X] [Y])
{
    INT I,J;
    浮 - [R;
    对于(i = 1; I< = X,我++){
        为(J = 1; J< = Y; J ++){
            R = RAND()/((浮点)RAND_MAX + 1);
            如果(R小于0.5){
                数组[I] [J] = I * X + J;
            }
            其他{
                数组[I] [J] = I * X + J;
            }
        }
    }
}

问题1:
我设置的宇宙(变量xDim和yDim)的尺寸。我打印出来的线45(查看评论//这里的值好)。然后,我打电话 initializeUniverseFromFile(inputPath,xDim,yDim,老);
和尺寸的一个值被改变。我不知道为什么。这就是为什么我做这个变量的临时副本,因为我花了2小时寻找那个错误。我甚至在那个 initializeUniverseFromFile 函数的最后打印出这个变量,它们是很好的。但是,当我回到主试(50行),该值被改变。这是小问题。更糟的是:

问题2
我有一个指针
    INT(*旧)[xDimB];

xDimB是xDim + 2,因此它总是比xDim

更大

我初始化函数数组
allocateMemoryFor2DArray(xDimB,yDimB)

然后我做到这一点:

  print2DArray(xDim,yDim,老); //这工作正常
的printf(在主:yDim:%D,xDim数:%d \\ n,yDim,xDim); //尺寸都很好
的printf(%d个\\ N,老[0] [0]); //这工作正常
对于(i = 0; I< = xDim ++ I)
     的printf(%d个老[0] [i]; //这工作太细
的printf(%d个\\ N,老[2] [2]); //分割失败

印刷与功能全阵列是罚款
从第一行打印值都很好
从阵列的中间值打印错误创建


解决方案

  

我把宇宙的尺寸(变量xDim和yDim)


您需要这些包含有效数字的的声明中沃拉斯 INT(*旧)[xDimB]; INT(*新)[xDimB]; 。移动这些VLA声明到后一点在节目中,当 xDim yDim 已经知道,核实值。

I'm trying to write a code for a Conway's Game of Life in C. I have some problems with 2D array which contain my universe. I will show you a parts of code that cause me a problems. Actually there a two problems that I can't handle.

#include <stdio.h>
#include <stdlib.h>
#include "file2ppm.h"

typedef enum { false, true } bool;

void *allocateMemoryFor2DArray(int x, int y);                                   //allocate memory for 2D array
void initializeUniverseFromFile(char* path, int x, int y, int array[x][y]);     //set values of cells from a file   
void initializeUniverseRandomly(int x, int y, int array[x][y]);                 //set random values 
int getNumberOfColumns (FILE *file);                                            //get number of columns in file (yDim of Universe)
int getNumberOfLines (FILE *file);                                              //get number of lines in file (xDim of Universe)
void print2DArray (int x, int y, int array[x][y]);                              //print 2D array    
void setDimensionsFromFile(char* path,int* xDim, int* yDim, int* xDimB, int* yDimB);//set dimensions of Universe

int main(int argc, char * argv[])
{
    int i, j, n;        //loop indexes
    int nsteps;         //Number of generations
    int im, ip, jm, jp; //neighbour boundaries
    int yDim, xDim;     //Universe boundarier defined by user (Living area);
    int xDimB, yDimB;   //Universe boundaries expanded to each side by 1
    int nsum, isum;     //sum of neighbours, sum of alive cells after iteration
    //int **old, **new; //Universe 
    int (*old)[xDimB];      //Universe
    int (*new)[xDimB];      //Universe

    float x;            //to randomize first population
    char *inputPath;    //Path to file with ixDimBtial uxDimBverse
    char *outputPath;   //Path to output ppm files


    //temporary copy
    int yDim_copy, xDim_copy;

    printf("argc: %d\n", argc);
    switch (argc){
        case 4:         //Read the initial Universe from file
            //Take arguments
            nsteps = atoi(argv[1]); //Get number of iterations
            outputPath = argv[2];   //Get path for outputimages
            inputPath = argv[3];    //File with initialize uxDimBverse;
            setDimensionsFromFile(inputPath, &xDim, &yDim, &xDimB, &yDimB);
            old = allocateMemoryFor2DArray(xDimB, yDimB);   //Alocate memory for expanded Universes
            new = allocateMemoryFor2DArray(xDimB, yDimB);
            printf("Before initialize: yDim: %d, xDim: %d\n", yDim, xDim);      //Here the values are good
            //tmp copy
            yDim_copy = yDim;
            xDim_copy = xDim;
            initializeUniverseFromFile(inputPath, xDim, yDim, old);
            printf("After initialize: yDim: %d, xDim: %d\n", yDim, xDim);       //And here one dim is changed
            yDim = yDim_copy;       //I took a copy to avoid this problem for now
            xDim = xDim_copy;

            printf("After taking from copy: yDim: %d, xDim: %d\n", yDim, xDim);//Here dimensions are good again
            memcpy (new, old, xDimB*yDimB*sizeof(old[xDimB][yDimB]));           //Copy old to new
            break;


        default:
            printf("Usage: %s iter_number, output_name, yDim, xDim\n", argv[0]);
            printf("or\n");
            printf("Usage: %s iter_number, output_name, ixDimBtial_input_name\n", argv[0]);
            printf("Note: Initial file have to be in ./data/\n");
            return 1;
    }

    print2DArray(xDim, yDim, old);      //this works fine
    printf("In main: yDim: %d, xDim: %d\n", yDim, xDim);
    printf("%d\n", old[0][0]);          //this works fine
    printf("%d\n", old[2][2]);          //Segmentation failure

    return 0;
}

void *allocateMemoryFor2DArray(int x, int y){
    int (*array)[y] = malloc( sizeof(int[x][y]) );      //Allocate memory
    if (array == NULL) {                                /* always check the return of malloc */
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    return array;
}

int getNumberOfColumns (FILE *file){
    int yDim = 0;
    char ch;

    do 
    {
        ch = getc(file);                            //Get 1 char from file

        if (ch == '\n')             //If ch is new line
        {
            rewind(file);           //Move file pointer to beginxDimBng of file
            return yDim;            //Found number of columns       
        }       
        else                
            ++yDim;

    }while (ch != EOF);
}

int getNumberOfLines (FILE *file){
    int xDim = 0;
    char ch;

    do  
    {
        ch = getc(file);                            //Get 1 char from file
        if(ch == '\n')                              //If new line
        {
            ++xDim;                             //Increase xDim (another row)
        }
    }while(ch != EOF);
    rewind(file);                                   //Move file pointer to beginxDimBng of file
    return xDim;
}


void print2DArray (int x, int y, int array[x][y])
{
    int i, j;
    printf("x: %d, y: %d\n", x, y);
    for (i = 1; i <= x; ++i) 
    {
        for (j = 1; j <= y; ++j) 
        {
            printf("%d ", array[i][j]);
        }
        printf("\n");
    }
}

void setDimensionsFromFile(char* path, int* xDim, int* yDim, int* xDimB, int* yDimB)
{
    FILE *file;
    int i,j;
    file = fopen(path, "r");        //open file 
    if (file)
    {
        *yDim = getNumberOfColumns (file);                  
        *xDim = getNumberOfLines (file);
        *xDimB = *xDim + 2;  // add 2 for left and right torus topology
        *yDimB = *yDim + 2;
        if (*xDim > 0 && *yDim > 0)
        {   
            printf("UxDimBverse dimension %d x %d\n", *xDim , *yDim);
        }           
        else
        { 
            perror("Wrong initialize file");
            exit(EXIT_FAILURE); 
        }       

        fclose(file);                       //Close file
    }
    else
    {
        perror("Open initialize file error");   
        exit(EXIT_FAILURE);
    }
}


void initializeUniverseFromFile(char* path, int x, int y, int array[x][y])
{ 
    FILE *file;
    int i,j;
    file = fopen(path, "r");        //open file 
    if (file)
    {
        //IxDimBtialize array
        char *ch;
        for (i = 1; i <= x; i++)
        {
            //printf("i: %d ", i);
            for (j = 1; j <= y; j++)
            {
                //printf("j: %d ", j);
                if (fscanf(file, "%c", ch) != 1)
                {
                    perror("Read error\n");
                }
                else if (isdigit((unsigned char)*ch))
                {
                    printf("%d", atoi(ch));
                    array[i][j] = atoi(ch);
                } 
                else 
                {
                    //printf("Numer znaku: %d ", ch);
                    j--;
                }
            }
            printf("\n");
        }
        printf("Done reading\n");
        fclose(file);           //Close file 
    } 
    else 
    {               //File open error
        perror("Open initialize file error");   
        exit (EXIT_FAILURE);
    }
    printf("In initialize yDim: %d, xDim: %d\n", x, y);
}

void initializeUniverseRandomly(int x, int y, int array[x][y])
{
    int i, j;
    float r;
    for (i = 1; i <= x; i++) {
        for (j = 1; j <= y; j++) {
            r = rand() / ((float)RAND_MAX + 1);
            if (r<0.5) {
                array[i][j] = i*x+j;
            }
            else {
                array[i][j] = i*x+j;
            }
        }
    }
}

Problem 1: I set the dimensions of universe (variables xDim and yDim). I print them in line 45 (check comment //Here the values are good). Then I call initializeUniverseFromFile(inputPath, xDim, yDim, old); And one of the dimensions values is changed. I have no idea why. That's why I make temporary copy of this variables, because I've spent 2 hours looking for that error. I even print out this variables at the end of that initializeUniverseFromFile function, and they are fine. But when I'm back in main again (line 50), the value is changed. This is minor problem. The worse is:

Problem 2 I have a pointer int (*old)[xDimB];

xDimB is xDim+2 so it is always bigger than xDim

I initialize the array with function allocateMemoryFor2DArray(xDimB, yDimB)

Then I do this:

print2DArray(xDim, yDim, old);      //this works fine
printf("In main: yDim: %d, xDim: %d\n", yDim, xDim); //Dimensions are fine
printf("%d\n", old[0][0]);          //this works fine
for (i=0; i<=xDim; ++i)
     printf("%d ", old[0][i];       //this works fine too
printf("%d\n", old[2][2]);          //Segmentation failure

Printing whole array with function is fine Printing values from first row are fine Printing value from middle of array create error.

解决方案

I set the dimensions of universe (variables xDim and yDim)

You need these to contain valid numbers before you declare the VLAs int (*old)[xDimB]; and int (*new)[xDimB];. Move these VLA declarations to a latter point in the program, when xDim and yDim have known, verified values.

这篇关于用C二维数组的指针访问,分段故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆