【问题标题】:Why my program gets a segfault in linux-gcc but not on mingw-gcc?为什么我的程序在 linux-gcc 中出现段错误,但在 mingw-gcc 中没有?
【发布时间】:2015-12-03 12:58:22
【问题描述】:

我用 C 编写了一个程序。问题是当我在 Linux/Unix 环境中编译这个程序时,我遇到了段错误。但是当我在 Windows 中使用 minGW 编译它时它工作正常。基本上在程序中我有一个多维数组。当我在 Linux/Unix 中的 gdb 中编译和调试时,我随机丢失了一行多维数组。当我尝试访问该行中的每一列时,突然无法访问所有列。我的整排都迷路了。

错误:程序收到信号 SIGSEGV,分段错误。

注意:isItDone()、oneToTwo() 和 checkAroundTwo() 很可能不是问题所在。我尝试在没有它们的情况下运行程序,但它仍然显示错误。

代码:

int main( int argc, char *argv[] ){
    FILE * output;
    output = fopen("output.txt", "w");
    srand(time(NULL));
    int size = 0; // Resetting before taking arguments
    int evaltime = 0; // Resetting before taking arguments
    int rand1, rand2;
    int counter, counter2, counter3;
    if(argc == 3){
        size = atoi(argv[1]);
        evaltime = atoi(argv[2]);
    }
    else{
        return 0;
    }
    double *evaltimes = (double*)calloc(evaltime , sizeof(double)); // The array of the results we got.
    for(counter2 = 0; counter2 < evaltime; counter2++){
        int cellnumbers = 0;
        int **ground = (int**)malloc(size * sizeof(int)); //Mallocating for every iteration
        for(counter = 0; counter < size; counter++){
            ground[counter] = (int*)calloc(size, sizeof(int)); // Initializing all the 0.
        }
        while(!isItDone(ground, size)){ // It's finished when last row is 2.
            rand1 = rand() % size;
            rand2 = rand() % size; // Take two random numbers for picking in array limit.
            printf("%d %d\n", rand1, rand2);
            if(rand1 == 0){ // Is it a top cell
                if(ground[rand1][rand2] == 0){
                    ground[rand1][rand2] = 2;
                    cellnumbers++; // Increment when a cell is picked.
                }
            }
            else{
                if(ground[rand1][rand2] == 1 || ground[rand1][rand2] == 2) // The cell is already opened
                    continue;
                else{
                    ground[rand1][rand2] = 1; // Defaulting to 1 before control
                    cellnumbers++;
                    oneTotwo(ground, size, rand1, rand2);
                }
            }
        }
        if(counter2 == evaltime - 1){ // Printing the last variation
            for(counter3 = 0; counter3 < size; counter3++){
                for(counter = 0; counter < size; counter++){
                    fprintf(output, "%d  ",ground[counter3][counter]);
                }
                fprintf(output, "\n");
            }
        }
        evaltimes[counter2] = (double)cellnumbers / (double)(size*size);
        for(counter = 0; counter < size; counter++)
            free(ground[counter]);

        free(ground);
    }
    double meany = mean(evaltimes, evaltime);
    double stddeviation = stddev(evaltimes, evaltime, meany);
    fprintf(output, "mean()  =  %f \n", meany);
    fprintf(output, "stddev()  =  %f",stddeviation);  
    fclose(output);
    return 0;
}

我认为错误很可能在于 main 但这是我的功能。

int isItDone(int **p, int size){
    int counter;
    for(counter = 0; counter < size; counter++){
        if(p[size - 1][counter] == 2 && (p + size - 1) != 0)
            return 1;
    }
    return 0;
}

void oneTotwo(int **p, int size, int rand1, int rand2){
    //Checking the Upper Cells
    if(rand1 < size - 1){ // Making sure no control if it is the last cell.
        if(p[rand1 + 1][rand2] == 2){
            p[rand1][rand2] = 2;
            checkAroundTwo(p, size, rand1, rand2);
        }
    }
    if(rand1 > 0){
        if(p[rand1 - 1][rand2] == 2){
            p[rand1][rand2] = 2;
            checkAroundTwo(p, size, rand1, rand2);
        }   
    }
    if(rand2  < size - 1){
        if(p[rand1][rand2 + 1] == 2){
            p[rand1][rand2] = 2;
            checkAroundTwo(p, size, rand1, rand2);
        }
    }
    if(rand2 > 0){
        if(p[rand1][rand2 - 1] == 2){
            p[rand1][rand2] = 2;
            checkAroundTwo(p, size, rand1, rand2);
        }
    }
}

void checkAroundTwo(int **p, int size, int rand1, int rand2){
    if(rand1 < size - 1){
        if(p[rand1 + 1][rand2] == 1){
            p[rand1 + 1][rand2] = 2;
            checkAroundTwo(p, size, rand1 + 1, rand2);
        }
    }
    if(rand1 > 0){
        if(p[rand1 - 1][rand2] == 1){
            p[rand1 - 1][rand2] = 2;
            checkAroundTwo(p, size, rand1 - 1, rand2);
        }
    }
    if(rand2 < size - 1){
        if(p[rand1][rand2 + 1] == 1){
            p[rand1][rand2 + 1] = 2;
            checkAroundTwo(p, size, rand1, rand2 + 1);
        }
    }
    if(rand2 > 0){
        if(p[rand1][rand2 - 1] == 1){
            p[rand1][rand2 - 1] = 2;
            checkAroundTwo(p, size, rand1, rand2 - 1);
        }
    }
}

double mean(double *p, int size){
    double sum = 0.0000000;
    int counter;
    for(counter = 0; counter < size; counter++)
        sum += p[counter];

    return sum / (double)(size);
}

double stddev(double *p, int size, double mean){
    double sum = 0.0000000;
    int counter;
    for(counter = 0; counter < size; counter++)
        sum += sqr(((double)p[counter] - mean));

    return sqrt(sum / (double)(size - 1)); 
}

double sqr(double x){
    return x*x;
}

double sqrt(double x){
    int counter = 0;
    while(sqr(counter) < x){
        counter++;
    }
    double s = counter;

    for(counter = 0; counter < 50; counter++){
        s = (double)1/2 * (double)(s + x/s);
    }
    return s;
}

让我们假设 int array[10][10] 更奇怪的事情是,在 gdb 中,例如当我丢失 array[5] 行时,我尝试从它之前的行访问它。例如数组[4][10]。当我这样做时“数组[4][10] = 49”。为什么是这样? Rest is (array[4][12], array[4][13] etc.) 是我指定的 0。为什么突然从第 4 行获得的第 5 行的第一个元素变成 49 ?我不明白。

【问题讨论】:

  • 阅读undefined behavior。使用gcc -Wall -Wextra -g 编译您的代码。使用valgrindgdb 调试器
  • 请注意,当您将内存分配给二维数组时,您实际上需要最初分配内存 sizeof(int*) 而不仅仅是 sizeof(int),因此您应该更改:int **ground = (int**)malloc(size * sizeof(int));int **ground = (int**)malloc(size * sizeof(int*));
  • @MPI_What 非常感谢!这实际上解决了我的问题。我怎么会错过呢?!该程序运行良好,符合预期,感谢您的帮助。
  • 没问题!不知道会不会。在这种情况下,我会将其写成实际答案,如果您想帮助未来的用户,您可以接受它:)。
  • OT:只是不要转换 malloc() 的结果,因为它在 C 中不需要也不推荐。

标签: c arrays linux gcc segmentation-fault


【解决方案1】:

当您将内存分配给二维数组时,您正在分配一个指针数组,每个指针都指向一个内存块。

这意味着当您执行初始malloc 时,您需要分配...sizeof(int*) 而不是...sizeof(int)

简而言之,改变这一行:

int **ground = (int**)malloc(size * sizeof(int));

到:

int **ground = (int**)malloc(size * sizeof(int*));

【讨论】:

  • 或者更安全的使用:int **ground = malloc(size * sizeof *ground);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
相关资源
最近更新 更多