【问题标题】:Why does this piece of code work and the other doesn't? (pointers and linked lists)为什么这段代码有效而另一部分无效? (指针和链表)
【发布时间】:2019-12-13 12:07:06
【问题描述】:

我正在使用 SDL 用 C 语言开发一个简单的游戏,我需要制作一个链表来存储玩家可以射击的子弹。

我尝试了两件事:

typedef struct{
  SDL_Rect *bullet_sprite; // sprite of the bullet
  struct Bullet *next_bullet; 
} Bullet;

Bullet bullets; // here I initialized bullets

在创建了一个名为bullets 的对象后,它将用于存储子弹,在这里我创建了一个名为shoot() 的空白,它只是创建了另一个子弹并将其存储在*next_bullet 中:

void shoot(Player *player){
  Bullet new_bullet;
  SDL_Rect rectangle = {player->x, player->y, BULLET_WIDTH, BULLET_HEIGHT};

  new_bullet.bullet_sprite = &rectangle;
  new_bullet.next_bullet = NULL;

  if(!player->n_of_bullets){
    bullets = new_bullet;
    printf("first bullet\n");
  }
  else{
    new_bullet.next_bullet = &bullets;
    bullets = new_bullet;
    printf("another bullet\n");
  }

  player->n_of_bullets++;
}

但是,当玩家射击时,会产生分段错误。 (为什么?)

当我将代码更改为:

typedef struct{
  SDL_Rect *bullet_sprite;
  struct Bullet *next_bullet;
} Bullet;

Bullet *bullets = NULL;

shoot() 到:

  Bullet *new_bullet = malloc(sizeof(Bullet));
  SDL_Rect rectangle = {player->x, player->y, BULLET_WIDTH, BULLET_HEIGHT};

  new_bullet->bullet_sprite = &rectangle;
  new_bullet->next_bullet = NULL;

  if(!player->n_of_bullets){
    bullets = new_bullet;
    printf("first bullet\n");
  }
  else{
    new_bullet->next_bullet = bullets;
    bullets = new_bullet;
    printf("another bullet\n");
  }

  player->n_of_bullets++;

它似乎工作得很好。 我只是想知道为什么会这样。谁能指出我的错误以及为什么在第一个示例中给出了分段错误?

【问题讨论】:

  • 您需要了解,在函数返回后,局部变量变得不可用,因此任何指向本地存储的指针都变得无效。 new_bulletrectangle 都是如此。因此,您认为“工作正常”的版本实际上并非如此,因为您的指针 bullet_sprite 设置为局部变量 rectangle 的地址,一旦函数返回,它就无效了。

标签: c pointers linked-list segmentation-fault nodes


【解决方案1】:

shoot() 函数的第一个版本中,new_bullet 结构默认分配在堆栈 内存中。这意味着当离开函数时,这个内存部分将被释放并用于其他目的。我认为问题出在此处:您将 bullets 结构重新定位在 new_bullet 地址处,该地址应仅在此函数内部使用。

shoot() 的第二个版本是正确的,因为malloc() 将在 heap 内存中分配新变量,并且在离开函数时不会被释放。

顺便说一句,您可以在每次不再需要子弹时使用free()。因为现在你的程序在每次你的炮手射击时都会在内存中分配一个新的结构,但从不释放它们。

希望对你有帮助。

【讨论】:

  • Nit ...“new_bullet 结构具有自动存储持续时间,存储在函数堆栈中创建。”和“.. 此内存部分(函数堆栈)将在函数返回时释放以供重用,并且返回后对该内存区域中变量的任何引用都会调用 未定义的行为
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2013-12-15
  • 2019-01-03
  • 2014-02-02
相关资源
最近更新 更多