C 为什么这段代码有效而另一段代码无效';T(指针和链表)

C 为什么这段代码有效而另一段代码无效';T(指针和链表),c,pointers,linked-list,segmentation-fault,nodes,C,Pointers,Linked List,Segmentation Fault,Nodes,我正在用SDL用C开发一个简单的游戏,我需要制作一个链表来存储玩家可以射击的子弹 我尝试了两件事: typedef struct{ SDL_Rect *bullet_sprite; // sprite of the bullet struct Bullet *next_bullet; } Bullet; Bullet bullets; // here I initialized bullets 在创建了一个名为项目符号的对象(用于存储项目符号)之后,我在这里创建了一个名为shoot

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

我尝试了两件事:

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

Bullet bullets; // here I initialized bullets
在创建了一个名为
项目符号
的对象(用于存储项目符号)之后,我在这里创建了一个名为
shoot()
的空区,该空区仅创建另一个项目符号并将其存储在
*下一个项目符号
中:

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++;
它似乎工作得很好。
我只是想知道为什么会这样。有人能指出我的错误以及第一个示例中出现分段错误的原因吗?

在第一个版本的
shoot()
函数中,
新的\u bullet
结构默认分配在堆栈中。这意味着当离开函数时,该内存段将被释放并用于其他目的。我认为问题就在这里:您将
项目符号
结构重新定位到
新的\u项目符号
地址,该地址只应在该函数中使用

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

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


我希望它能帮助你

在第一个版本的
shoot()
函数中,
新的\u bullet
结构默认分配到堆栈中。这意味着当离开函数时,该内存段将被释放并用于其他目的。我认为问题就在这里:您将
项目符号
结构重新定位到
新的\u项目符号
地址,该地址只应在该函数中使用

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

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


我希望它能帮助你

您需要了解,局部变量在函数返回后变得不可用,因此指向本地存储的任何指针都将无效。这对
new\u bullet
rectangle
都是如此。因此,您认为“工作正常”的版本事实上并非如此,因为您的指针
bullet\u sprite
,设置为局部变量
rectangle
的地址,一旦函数返回就无效。您需要了解,局部变量在函数返回后变得不可用,因此,任何指向本地存储的指针都将无效。这对
new\u bullet
rectangle
都是如此。因此,您认为“工作正常”的版本事实上并非如此,因为您的指针
bullet\u sprite
(设置为局部变量
rectangle
的地址)在函数返回时就无效。Nit。。。“新的\u bullet结构具有自动存储持续时间,并在函数堆栈中创建存储。”和“。此内存部分(函数堆栈)将在函数返回时释放以供重用,返回后对该内存区域中变量的任何引用都会调用未定义的行为。Nit…”新的_bullet结构具有自动存储持续时间,在函数堆栈中创建存储。“和”。。此内存部分(函数堆栈)将在函数返回时释放以供重用,并且在返回调用未定义的行为后,对该内存区域中变量的任何引用都将被释放。