【问题标题】:C - dynamic array in a struct - crash after reallocationC - 结构中的动态数组 - 重新分配后崩溃
【发布时间】:2017-07-04 11:11:53
【问题描述】:

我是 C 的新手,我试图在结构中创建一个动态数组,我需要向其中添加动态数量的项目。

如果我在初始化容器时使用带有大数字(如 +100000)的 malloc,则程序可以正常工作。

但是,如果我只是分配sizeof(struct ...) 内存,然后尝试使用realloc 重新分配,当我尝试向数组中添加新项目时程序会崩溃。即使我在重新分配时添加了 +1000000 大小,它仍然会崩溃,而如果我在最初分配时使用它,则相同的大小仍然有效。

减少代码以显示我的问题:

struct Station {
    char name[100];
};

struct StationContainer {
    int numberOfStations;
    struct Station *stations[];
};

struct StationContainer *makeContainer() {
    struct StationContainer *new;
    // If I add +1000000 in size here, the program works fine
    new = (struct StationContainer *) malloc(sizeof(struct StationContainer));

    if (new == NULL) {
        fprintf(stderr, "makeContainer: out of memory\n");
        exit(1);
    }

    new->numberOfStations = 0;

    return new;
}

int main(int argc, int argv[]) {

    // Initialize the container
    struct StationContainer *container;
    container = makeContainer();

    // Add new station to container
    struct Station *new;
    new = (struct Station *) malloc(sizeof(struct Station));

    if (new == NULL) {
        fprintf(stderr, "makeStation: out of memory\n");
        exit(1);
    }

    strcpy(new->name, name);

    // Add to the container
    // Even if I add +1000000 here, it still crashes below when I add new item
    container = (struct StationContainer *) realloc(container, sizeof(struct StationContainer) + 1000000);

    if (container == NULL) {
        fprintf(stderr, "makeStation: container out of memory\n");
        exit(1);
    }

    container->stations[container->numberOfStations] = new;
    container->numberOfStations++;


}

EDIT1: 在我的精简版中发现了问题,但是,一旦我返回完整版,我仍然收到错误。我收到了container out of memory。那是因为我的container->numberOfStations 在第一次增加后由于某种原因变得非常大。

我的完整代码在: codepad

adjacencies.txt 文件内容:

Baker Street, Bond Street, Regent's Park
Bond Street, Marble Arch, Baker Street, Oxford Circus, Green Park
Marble Arch, Bond Street
Green Park, Bond Street, Oxford Circus, Piccadilly Circus
Regent's Park, Baker Street, Oxford Circus
Oxford Circus, Bond Street, Regent's Park, Warren Street, Tottenham Court Road, Piccadilly Circus
Piccadilly Circus, Green Park, Oxford Circus, Leicester Square, Charing Cross
Warren Street, Oxford Circus, Goodge Street
Goodge Street, Warren Street, Tottenham Court Road
Tottenham Court Road, Oxford Circus, Goodge Street, Holborn, Leicester Square
Leicester Square, Piccadilly Circus, Tottenham Court Road, Covent Garden, Charing Cross
Charing Cross, Piccadilly Circus, Leicester Square
Covent Garden, Leicester Square, Holborn
Holborn, Tottenham Court Road, Chancery Lane
Chancery Lane, Holborn

当我制作电台时,如果我保持container->numberOfStations不变,就没有问题。但是,当我至少增加一次时,结合realloc,它会变成巨大的数字。示例输出:

Number of stations: 0
!Station name:[Baker Street]
Number of stations: 1
!Station name:[Bond Street]
Number of stations: 4067560
makeStation: container out of memory

我觉得某处出现了一个小错误,导致我的 numberOfStation 发生了剧烈变化,即使它应该只增加 1?

【问题讨论】:

  • 第一个注意事项:不要强制转换 malloc 返回值。第二点:不推荐调用变量newname 声明在哪里? strcpy(new->name, name);
  • 会改变的,我只是在听我的 Uni 讲座的笔记
  • 您能否使用gdb 提供一些输入和确切的错误行?
  • sizeof(struct StationContainer) + 1000000malloc()/realloc() 中没有意义,因为您希望分配的内存量为struct StationContainer 的多个大小 - 你是不是要写sizeof(struct StationContainer) * 1000000
  • @ChrisTurner no, + 1000000 仅用于调试,表明当我首先分配内存时它可以工作,但是当我尝试重新分配它时它不起作用。首先是的,它将是sizeof(struct(Station)) * numberOfStations

标签: c struct malloc realloc


【解决方案1】:

在发布的原始版本中,container->numberOfStations 未初始化。
在 makeContainer 中,您可能会考虑使用 calloc()memset() 将您的容器初始化为零 - 当您将新项目添加到结构时它工作得很好,并且它们仍然应该初始化为零。

在当前版本中,我没有发现任何错误,valgrind 也没有。我冒昧地在 100 个字符的限制范围内声明了 name

【讨论】:

  • 好眼光。没注意到你已经回答了。 :) 删除了我的。
  • 好地方,我在剪掉这个预览的代码时不小心把它删了。我现在将对其进行编辑以显示它的样子。
  • 我做了另一个编辑,显示了我是如何得到我的错误的。当我尝试将我的container->numberOfStations 增加一时,就会发生这种情况。我还添加了指向完整代码的链接codepad.org。非常感谢您的帮助!
【解决方案2】:

好吧-看看

struct StationContainer {
    int numberOfStations;
    struct Station *stations[];
};

所以stations 是指针

所以makeContainer 只是为指针等提供了足够的空间。您甚至没有为指针分配内存以获取信息,也没有初始化numberOfStations。它只是一个未初始化的指针

PS:这是否编译

   strcpy(new->name, name);

找不到name的声明

【讨论】:

  • 是的,他确实分配了。他用那个指针指向new
  • 嗯? name 未声明。 new->name 有记忆
  • @Tony container->stations 没有定义,所以你不能访问它的任何元素
  • 我的意思是他为StationContainer分配了内存。对于Station,他确实没有。我已经在 cmets 中指出了这一点。
  • 在我编辑的代码中,container->stations 工作正常,我可以从那里写入和读取至少 1 个站点。 container->numberOfStations 变得非常大,因此程序内存不足。
猜你喜欢
  • 2013-01-22
  • 2014-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
  • 2012-01-22
  • 1970-01-01
  • 2021-10-15
相关资源
最近更新 更多