C语言中的动态内存分配不起作用

3

我正在尝试制作一款需要 C 语言动态大小数组的游戏,但是我的代码不起作用,即使在我的另一个程序中相同的代码也能够工作。

这里是我的 #includes

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SwinGame.h" //API for graphics, physics etc
#include <math.h>

这里是我用到的相关结构体的typedef定义:
typedef struct position_data
{
  double x;
  double y;
} position_data;

typedef enum enemy_type_data {CIRCLE, TRIANGLE, SQUARE} enemy_type_data;

typedef struct enemy_data
{
  position_data location;
  enemy_type_data type;
  bitmap bmp;
  double health;
  double speed;
  int path_to;
} enemy_data;

typedef struct enemy_data_array
{
  int size;
  enemy_data *data;
} enemy_data_array;

以下是向数组添加元素的函数:

void add_enemy(enemy_data_array *enemies)
{
  enemy_data *new_array;
  enemies->size++;
  new_array = (enemy_data *)realloc(enemies->data, sizeof(enemy_data) * enemies->size);
  if (new_array) //if realloc fails (ie out of memory) it will return null
  {
    enemies->data = new_array;
    // enemies->data[enemies->size - 1] = read_enemy_data();
    printf("Enemy added successfully!\n");
  }
  else
  {
    printf("FAILED. Out of Memory!\n");
    enemies->size--;
  }
}

这是我的主程序中的函数调用和变量声明:

int main()
{
  path_data my_path[41];
  enemy_data_array enemies;
  enemies.size = 0;
  add_enemy(&enemies);
}

为什么这个不起作用?


发布的代码缺少一些关键细节,例如#include语句和bitmapposition_data的定义。编译时,请始终启用所有警告,然后修复这些警告。(对于gcc,至少使用:-Wall -Wextra -pedantic,我还使用:-std=gnu99 -Wconversion - user3629249
现在将编辑以添加这些详细信息。谢谢 @user3629249 - Andrew
3个回答

6

在使用具有自动存储期的未初始化变量时,通过传递不确定的值enemies->data,您引发了未定义行为。在使用add_enemy()之前,请先对其进行初始化。

int main()
{
  path_data my_path[41];
  enemy_data_array enemies;
  enemies.size = 0;
  enemies.data = 0; /* add this line */
  add_enemy(&enemies);
}

0 是一个空指针常量,可以安全地转换为指针 NULL。与 NULL 不同的是,0 可以在不包含任何头文件的情况下正常工作。当然,如果包含了正确的头文件,也可以使用 enemies.data = NULL;


2
在这种情况下,传递一个至少有一个成员初始化或赋值的自动结构体不是未定义行为。当realloc被调用到具有不确定值的指针上时,才会发生未定义行为。 - 2501

3

@2501的解释是完全正确的。另一个解决方案是将add_enemy()的实现更改为以下内容:

void add_enemy(enemy_data_array *enemies)
{
  enemy_data *new_array;

  // check if size was non-zero
  if (enemies->size++)
  {
    new_array = (enemy_data *)realloc(enemies->data, sizeof(enemy_data) * enemies->size);
  }
  // start new allocation
  else
  {
    new_array = (enemy_data *)alloc(sizeof(enemy_data) * enemies->size);
  }

  if (new_array) //if (re)alloc fails (ie out of memory) it will return null
  {
    enemies->data = new_array;
    // enemies->data[enemies->size - 1] = read_enemy_data();
    printf("Enemy added successfully!\n");
  }
  else
  {
    printf("FAILED. Out of Memory!\n");
    enemies->size--;
  }
}

2

失败是因为您没有清除“enemies”的内容。由于它是一个堆栈变量,它将包含堆栈上的任何垃圾数据。

在主函数中将enemies.data设置为NULL,然后再尝试一次。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接