【问题标题】:Dynamic Memory Allocation for array of structs结构数组的动态内存分配
【发布时间】:2020-04-18 14:25:12
【问题描述】:

所以我一直在做我的一个小项目,但我被困在了这个阶段。我不断收到段错误,我越来越绝望。我有 2 个结构

typedef struct {
    float time;
}Race;

typedef struct {
    char DriverName[50];
    int NoRaces;
    Race *races;
}Driver;

我必须为单个车手分配内存,然后在获得每个车手的比赛次数后为一组车手分配内存。这是我目前的代码

Driver *allocDriver(int noRaces) {
    Driver *driver;
    driver = (Driver *)malloc(sizeof(Driver));
    driver->NoRaces = noRaces;
    driver->races = (Race *)malloc(sizeof(Race));       

    return driver;}


Driver **allocDrivers(int driversNo, int *driversRacesNo) {
    int i;
    Driver **drivers;
    drivers = (Driver **)malloc(driversNo * sizeof(Driver *));
    for(i = 0; i < driversNo; i++)
        drivers[i] = allocDriver(driversRacesNo[i]);

    return drivers;}

【问题讨论】:

  • 您发布的内容看起来不错。尝试通过 valgrind 运行您的代码。如果你对内存管理不善,它会告诉你在哪里。
  • 我已经使用了 valgrind,它说“错误摘要:来自 0 个上下文的 0 个错误(抑制:0 个来自 0)”所以我不知道它可能是什么,我不断收到“分段错误(核心转储)”

标签: c arrays memory-management dynamic-memory-allocation


【解决方案1】:

这是一个关于结构表分配的“扩展”但简单的示例,在 ubuntu 18.04 上编译。希望它能够自我解释和说明。对于未来的开发和练习,尝试使用链表而不是数组。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct sRace {
    float time;
}Race;

typedef struct sDriver {
    char DriverName[50];
    int NoRaces;
    Race *races;
}Driver;


typedef struct sDriversTable {
    int numdrivers;
    Driver** drivers;
} DriversTable;



Driver *allocDriver(char* name, int numraces)
{
    Driver *driver = calloc(1, sizeof(Driver));
    driver->NoRaces = numraces;
    strcpy(driver->DriverName, name);
    driver->races = calloc(numraces,sizeof(Race));
    return driver;
}

DriversTable* allocDriversTable(int numdrv)
{
     DriversTable* dt = calloc(1,sizeof(DriversTable));
     dt->numdrivers = numdrv;
     dt->drivers = calloc(dt->numdrivers, sizeof(Driver*));
    return dt;
}


void addDriver(DriversTable* drv, char* name, int numraces)
{
    for(int i = 0; i < drv->numdrivers; i++)
    {
        if( drv->drivers[i]  == NULL)
        {
            drv->drivers[i] = allocDriver(name, numraces);
            break;
        }
    }
}

void setDriverTimeForTheRace(DriversTable* drv, char* name, int raceindex, float time)
{

    for(int i = 0; i < drv->numdrivers; i++)
    {
        if( !strcmp(drv->drivers[i]->DriverName,name) )
        {
            if( raceindex < drv->drivers[i]->NoRaces )
            {
               drv->drivers[i]->races[raceindex].time = time;
            }
            else
            {
                printf("invalid race index. %d, (max. for the driver %s is %d\n",raceindex,drv->drivers[i]->DriverName, drv->drivers[i]->NoRaces -1);
            }
            break;
        }
    }
}

void printDriversTable(DriversTable* drv)
{
    for(int i = 0; i < drv->numdrivers; i++)
    {
        if( drv->drivers[i]  != NULL)
        {
            printf("Driver:%s, Races: %2d\n", drv->drivers[i]->DriverName, drv->drivers[i]->NoRaces);
            for(int j = 0; j < drv->drivers[i]->NoRaces; j++)
            {
                if(drv->drivers[i]->races[j].time > 0.0 )
                    printf("{%4.2f}", drv->drivers[i]->races[j].time);
                else
                    printf("{%4s}", "n/a");
            }
            printf("\n");
        }
    }
}

void ReleaseResources(DriversTable** dt)
{
    DriversTable* drv = *dt;
    if( drv == NULL)
    {
      printf("nothing to release!\n");
      return;
    }
    for(int i = 0; i < drv->numdrivers; i++)
    {
        if( drv->drivers[i]  != NULL)
        {
            free(drv->drivers[i]->races);
            drv->drivers[i]->races = NULL;
            free(drv->drivers[i]);
            drv->drivers[i]=NULL;
        }
    }

    free(drv->drivers);
    drv->drivers = NULL;
    free(drv);
    *dt = NULL;
    printf("released!\n");
}

int main()
{
    DriversTable *drv = allocDriversTable(10);
    addDriver(drv,"Emerson", 6);
    setDriverTimeForTheRace(drv,"Emerson",1, 34.5);
    setDriverTimeForTheRace(drv,"Emerson",2, 33.6);
    setDriverTimeForTheRace(drv,"Emerson",7, 34.5);
    addDriver(drv,"Lake",7);
    setDriverTimeForTheRace(drv,"Lake",3, 21.5);
    setDriverTimeForTheRace(drv,"Lake",5, 22.6);
    setDriverTimeForTheRace(drv,"Lake",7, 23.5);
    addDriver(drv,"Palmer",8);
    setDriverTimeForTheRace(drv,"Palmer",4, 21.5);
    setDriverTimeForTheRace(drv,"Palmer",6, 22.6);
    setDriverTimeForTheRace(drv,"Palmer",7, 23.5);
    printDriversTable(drv);
    ReleaseResources(&drv);
    ReleaseResources(&drv);
    return 0;
}

【讨论】:

    【解决方案2】:

    虽然我不确定,因为我不知道你如何从main 中调用这些,也不知道作业的内容;我怀疑您需要更改以下行;

    driver->races = (Race *)malloc(sizeof(Race));
    

    喜欢:

    driver->races = (Race *)malloc(noRaces * sizeof(Race));
    

    例如,您的代码存储 5 作为比赛次数,但没有为 struct Race 分配 5 个内存空间(我认为,此结构用于比赛结果);目前,它只分配struct Race 的一个mem-width。

    【讨论】:

    • 在主要给我段错误的行是: TDriver** drivers = allocDrivers(3,array);我按照您的建议进行了更改,但仍然没有解决错误。
    • 没关系,似乎我正在向函数发送一个“int 指针”作为参数,这给了我错误,我不知道为什么,但就是这样。感谢您的回复,您让我免于另一个错误。 :)
    • malloc的返回不用投,没必要。请参阅:Do I cast the result of malloc? 使用取消引用的指针设置 type-size 将始终提供正确的大小,例如driver-&gt;races = malloc(noRaces * sizeof *driver-&gt;races); 不要忘记检查每个分配的返回,例如if (!driver-&gt;races) { perror ("malloc-driver-&gt;races"); return NULL; }
    猜你喜欢
    • 2013-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    相关资源
    最近更新 更多