首页 > 解决方案 > 如何为 C 中的结构正确分配内存?

问题描述

我不知道如何在我的 C 程序中为结构分配内存而不会出现分段错误。

typedef struct Player{
      char *name,  *surname;
      int xp;
} Player;

typedef struct Team{
      char *name;
      Player *player;
} Team;

typedef struct List
{
    Team *team;
    struct List *next;
} List_Node;

我需要列出一个包含一系列球员的球队名单,但为了让我的程序不会出现 Segfault,我需要 malloc 每个结构的每个成员。然后我必须释放每个结构的每个成员。这是一个相当大的项目,我遇到堆损坏错误,我不知道我是否正确初始化了我的结构。

在 main 中初始化了指针。

List_Node *list_node = (List_Node*)malloc(sizeof(List_node));

和功能

void create_list_Node(List_Node *temp)
{
    temp->team = malloc....
    temp->team->name = malloc....
    temp->team->player = malloc....
    temp->team->player->name = malloc....
    temp->team->player->surname = malloc....
    temp->next = NULL;
}

以节点作为参数调用。

标签: cdynamic-memory-allocation

解决方案


为了减少“分散在各处的许多内存块”(以及跟踪所有小块分配/释放位置的麻烦),您可以为多个事物分配一块内存(例如,结构加字符串) . 例如:

typedef struct Player{
      char *name,  *surname;
      int xp;
} Player;

typedef struct Team{
      struct Team *next;
      char *name;
      Player *player;
} Team;

Player *createPlayer(char *name, char *surname, int xp) {
    Player *newPlayer;
    int len1, len2;

    len1 = strlen(name);
    len2 = strlen(surname);
    newPlayer = malloc(sizeof(Player) + len1+1 + len2+1);
    if(newPlayer != NULL) {
        newPlayer->next = NULL;
        newPlayer->name = (char *)newPlayer + sizeof(Player);
        memcpy(newPlayer->name, name, len1+1);
        newPlayer->surname = newPlayer->name + len1+1;
        memcpy(newPlayer->surname, surname, len2+1);
        plyer->xp = xp;
    }
    return newPlayer;
}

Team *createTeam(Player *player, char *name) {
    Team *newTeam;
    int len1;

    len1 = strlen(name);
    newTeam = malloc(sizeof(Team) + len1+1);
    if(newTeam != NULL) {
        newTeam->next = NULL;
        newTeam->name = (char *)newTeam + sizeof(Team);
        memcpy(newTeam->name, name, len1+1);
        newTeam->player = player;
    }
    return newTeam;
}

这也意味着很容易释放任何东西——例如,你可以free(player)不用弄乱各个字段。

注意:我摆脱并在结构中List_Node放置了一个next字段。Team这有助于提高迭代性能(也减少过多的 malloc/free)。要理解这一点,假设您要列出所有团队名称并执行以下操作:

    while(node != NULL) {
        printf("name: %s\n", node->team->name)
        node = node->next;
    }

在这种情况下; CPU 在等待node从内存中获取时停止,然后在等待node->team从内存中获取时停止。现在想象一下:

    while(team != NULL) {
        printf("name: %s\n", team->name)
        team = team->next;
    }

在这种情况下; CPU 停止一次而不是两次,因此迭代列表更快。


推荐阅读