【问题标题】:Segmentation fault on reallocating of memory重新分配内存时的分段错误
【发布时间】:2020-03-29 09:54:51
【问题描述】:

我需要为面包店管理制作一个程序,我已经完成了结构和三个指针数组,它们必须包含这些结构的对象的指针。但我无法创建添加新面包店的功能,因为它需要动态内存分配。我试过这样做,但它会在 realloc 上抛出 Segmentation Fault。对于如何为这些数组正确重新分配内存以添加元素的任何建议,我将不胜感激。代码中的其他错误也可以随意提出cmets,我只是在学习。

typedef struct BakeryType {
    char *name;
} BakeType;

typedef struct Bakerys {
    char *name;
    BakeType *type;
    char *photo;
    float weight;
    int portions;
    float price;
    char *description;
} Bakery;

Bakery *bakeryList[0];
BakeType *bakeTypeList[0];

void addBakery() {
    Bakery new;
    *bakeryList = realloc(*bakeryList, (sizeof(bakeryList)/ sizeof(Bakery))+ 1);//Segmentation Fault
    bakeryList[sizeof(bakeryList)/sizeof(Bakery)]=&new;
}


【问题讨论】:

  • 您发布的代码似乎超出了您的问题的合理范围。请阅读How to Ask 以及如何制作minimal reproducible example;提供 MRE 可以帮助用户回答您的问题,并且未来的用户会与您的问题相关。 idownvotedbecau.se/nomcve
  • C 中不能有零大小的数组。这是一些 gcc 方言吗?同样出于对混淆的热爱,摆脱那些宏。如果需要,使用实函数。
  • @Lundin 它编译并运行零大小数组时没有警告,我怀疑我不能这样做,但编译器什么也没说,所以我让它去。如果我将数组大小更改为 1,问题仍然存在。好的,将重新制作宏以使其正常运行,谢谢。
  • @Lundin 你可以在 C 中使用零元素数组。试试看。
  • @WillisBlackburn 不,你不能,期间。使用 C 语言兼容的编译器 自己尝试一下。 godbolt.org/z/W4JFcV

标签: c arrays segmentation-fault structure realloc


【解决方案1】:

bakeryList 是指向Bakery 的指针的零元素数组。它有零指针的空间。

然后你将这个数组的第一个元素(*bakeryListbakeryList[0] 相同)设置为从realloc 返回的任何内容。所以你正在覆盖一些东西,它可能会从那里走下坡路。

我认为您希望 bakeryList 只是指向 Bakery 的指针。这就是动态分配数组在 C 中的工作方式:定义指向第一个元素的指针并使用指针数学运算(例如,bakeryList[5]*(bakeryList + 5))来访问其他元素。

另一个问题是您对sizeof(bakeryList) 的使用。 sizeof 是由编译器评估的运算符。它在运行时不会改变。 sizeof(bakeryList) / sizeof(Bakery) 将评估为零,因为您将 bakeryList 定义为零元素数组。您需要另一个变量来跟踪运行时数组中实际有多少元素。

这样的事情会起作用:

int bakeryCount = 0;
Bakery *bakeryList = NULL;

void addBakery() {
    // Add one to the array.
    bakeryCount++;
    bakeryList = realloc(bakeryList, bakeryCount * sizeof (Bakery));
    // Create a pointer to the new element at the end of the array.
    Bakery *newBakery = bakeryList + bakeryCount - 1;
    // Set all the fields. Note that they will probably contain
    // garbage so you should set them all.
    newBakery->name = ...
}

【讨论】:

  • 删除分配,问题依然存在。我认为它在 realloc 中失败了,因为我以某种方式搞砸了设置它的大小,但我不知道如何。
  • 我更新了答案。这段代码应该可以工作。如果您有任何问题,请告诉我。
  • 为什么我不能像这样将名称扫描到这个新元素:scanf("%s",newBakery->name);?它还会引发分段错误
  • "sizeof(bakeryList) / sizeof(Bakery) 将评估为零,因为您将 bakeryList 定义为零元素数组。"这是不正确的,因为 C 标准没有提到如果定义“零大小数组”会发生什么。相反,它明确表示数组的大小不能为零,违反 C11 6.7.6.2/1 的约束“... [ 和 ] 可能会分隔表达式...如果表达式是常量表达式,则它应具有更大的值比零。”因此,任何人都可以猜测 OP 的代码会做什么。可能它正在使用 GNU C 非标准扩展等。
  • @Lundin 使用默认选项 gcc 和 clang 编译一个零元素数组并将 sizeof 报告为零,这正是您所期望的。看,我不是说零元素数组有用,但很明显sizeof 零元素数组为零。
猜你喜欢
  • 2017-11-21
  • 2016-09-29
  • 2020-11-04
  • 2021-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-12
  • 1970-01-01
相关资源
最近更新 更多