【问题标题】:Segmentation fault after a free()free() 后的分段错误
【发布时间】:2021-12-18 17:22:23
【问题描述】:

我正在尝试动态分配一个矩阵 N*N 并将随机数(介于 0 和 h-1 之间)放入其中。我还必须创建一个释放它的函数。问题是我必须使用结构,而且我不太习惯它们。结构“game_t”在另一个文件中定义并包含在内。

game_t * newgame( int n, int m, int t){
    game_t x, *p;
    int i,j;
    p=&x;
    x.t=t;
    x.n=n;    /* structure game has n,t,h,board as keys*/
    x.h=h;
    srand(time(NULL)); 
    x.board=malloc(n*sizeof(int*));    /*Allocate*/
    if (x.board==NULL) return NULL;
    for (i=0;i<n;i++){
              x.board[i]=malloc(n*sizeof(int));}
    for (i=0;i<n;i++){   /*put random numbers*/
             for (j=0;i<n;j++){
                     x.board[i][j]=rand()%h;}}
    return p;
}

void destroy(game_t *p){
    int i;
    for (i=0;i<p->n;i++){
        free(p->board[i]);}
    free(p->board);
}

【问题讨论】:

  • for (j=0;i&lt;n;j++) 看起来不正确 (ij)
  • 主要问题是p=&amp;x;这里你让p指向local变量x,这个变量的生命周期在函数newgame时结束返回。这使得指针无效。
  • 你在这里返回一个局部变量的地址:return p;,因为p指向x
  • x 存在于堆栈中。它在 newgame 之外不存在。
  • 除了所有的错误,您可能希望使用二维数组。见Correctly allocating multi-dimensional arrays

标签: c matrix segmentation-fault free


【解决方案1】:

您返回指向局部变量x 的指针。一旦你离开它们的作用域,局部变量就会消失。

game_t * newgame( int n, int m, int t){
    game_t x, *p;
    int i,j;
    p=&x;    // <<<< p points to the local variable x
    x.t=t;
    x.n=n;
    x.h=h;
    srand(time(NULL)); 
    x.board=malloc(n*sizeof(int*));
    if (x.board==NULL) return NULL;
    for (i=0;i<n;i++){
              x.board[i]=malloc(n*sizeof(int));}
    for (i=0;i<n;i++){
             for (j=0;i<n;j++){
                     x.board[i][j]=rand()%h;}}
    return p;
}

你可能想要这个:

game_t * newgame( int n, int m, int t){
    game_t *p = malloc(sizeof (*p));   // allocate memory for a new game_t
    int i,j;
    p->t=t;
    p->n=n;
    p->h=h;
    srand(time(NULL)); 
    p->board=malloc(n*sizeof(int*));
    if (p->board==NULL) return NULL;
    for (i=0;i<n;i++){
              p->board[i]=malloc(n*sizeof(int));}
    for (i=0;i<n;i++){
             for (j=0;i<n;j++){
                     p->board[i][j]=rand()%h;}}
    return p;
}

顺便说一句:您应该使用有意义的变量名。例如p 应命名为new 等。

奖励:只在程序开始时调用srand(time(NULL))一次

【讨论】:

  • 有道理!但是现在我收到一个错误,因为 *p 与 malloc 不兼容。在 `typedef struct game { int n, int h, int ** board} game_t` 之外定义的结构体 game_t`
  • @PhysicsStudent 您确切地得到了哪个错误?永远不要写“我遇到错误”,总是写逐字错误消息。
  • 我得到“malloc 参数 1 的不兼容类型”,它需要 size_t
  • 对不起,我的错,应该是malloc(sizeof (*p))。我刚刚编辑了问题
  • 哇,这比我想象的要容易!非常感谢它现在完美运行!
【解决方案2】:

p 是一个指向局部变量的指针,x。一旦离开函数newgame,该变量将不复存在,p 现在是一个悬空指针。您无权访问它。

解决方案很简单:从newgame 返回一个game_t,而不是newgame_t *,并且不要使用p

game_t newgame(int n, int m, int t) {
    game_t x;
    int i, j;
    x.t = t;
    x.n = n;    /* structure game has n,t,h,board as keys*/
    x.h = h;
    srand(time(NULL)); 
    x.board = malloc(n * sizeof (int*));    /*Allocate*/
    if (x.board == NULL) {
        perror("newgame");
        exit(1);
    }
    for (i = 0; i < n; i++) {
        x.board[i] = malloc(n * sizeof(int));
        if (x.board[i] == NULL) {
            perror("newgame");
            exit(1);
        }
    }
    for (i = 0; i < n; i++) {   /*put random numbers*/
        for (j = 0; i < n; j++) {
            x.board[i][j] = rand() % h;
        }
    }
    return x;
}

请注意,这意味着如果分配失败,您将无法再返回 NULL。我已经修改了代码以退出,但可能需要不同的策略(尽管可能不是:分配失败通常很难处理,并且退出 - 带有错误消息! - 是一个好的响应)。

【讨论】:

  • 问题是我被要求创建一个返回 * game_t 的函数 newgame !还是谢谢你!
  • @PhysicsStudent 在这种情况下,您需要 Jabberwocky 的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-13
  • 2015-10-03
  • 1970-01-01
  • 1970-01-01
  • 2011-01-19
相关资源
最近更新 更多