如何在C中为结构正确分配内存?

问题描述 投票:0回答:2

我不知道如何为我的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;
}

以节点作为参数调用。

c dynamic-memory-allocation
2个回答
1
投票

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

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会停止一次而不是两次,因此迭代列表会更快。


1
投票

如果我们使用此函数来创建一个空节点:

void create_list_Node(List_Node *temp)
{
    temp->team = calloc(1, sizeof(Team));
    temp->team->player = calloc(1, sizeof(Player));
    temp->next = NULL;
}

如何分配namn:s和surname取决于这些字符串的来源。如果你得到一个没有其他代码可以释放的分配指针,你可以“采用”指针:

char *mystring;
... code that allocates
temp->team->name = mystring;

如果你有一个本地字符串数组,只需复制它:

char local[100];
... code that fill it, maybe gets()
temp->team->name = strdup(local);

不要忘记释放字符串和结构!

© www.soinside.com 2019 - 2024. All rights reserved.