c - 检测到堆栈粉碎 : running program with dinamically allocated array of structures

标签 c memory-management struct

我正在编写以下程序:

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

int main(void)
{
    plane* planes=NULL;
    int size=0;

    readPlanes(&planes, &size);

    free(planes);
    planes=NULL;

    return EXIT_SUCCESS;
}


void readPlanes(plane** planes, int* size)
{
    char buffer[100]={'\0'};
    int airplaneID, modeli;
    float fuel;
    char modelc;
    int invent=0;
    int rettest=0;
    do{
        printf("Enter the number of planes:\n");
        fgets(buffer, 100, stdin);
        rettest=sscanf(buffer, "%d", size);
        if((*size)<=0)
        {
            printf("Invalid number of planes: enter a non negative number\n");
            rettest=0;
        }

    }while(rettest!=1);

    *planes=(plane*)calloc((*size), sizeof(plane*));

    for(invent=0; invent<(*size); invent++)
    {
        planes[invent]=calloc(1, sizeof(plane));

        do{
            rettest=0;
            printf("Enter the airplaneID:\n");
            fgets(buffer, 100, stdin);
            rettest=sscanf(buffer, "%d", &airplaneID);
            if(airplaneID<0)
            {
                printf("Invalid airplaneID: enter a positive number\n");
                rettest=0;
            }

        }while(rettest!=1);

        planes[invent]->airplaneID=airplaneID;

        do{
            rettest=0;
            printf("Enter the model:\n");
            fgets(buffer, 100, stdin);
            rettest=sscanf(buffer, "%c %d", &modelc, &modeli);
            if(modeli<0 || modelc<'A' || modelc>'Z')
            {
                printf("Invalid model: enter an uppercase letter followed by a non negative number\n");
                rettest=0;
            }

        }while(rettest!=2);

        planes[invent]->planemodel.letter=modelc;
        planes[invent]->planemodel.number=modeli;

        do{
            rettest=0;
            printf("Enter the fuel:\n");
            fgets(buffer, 100, stdin);
            rettest=sscanf(buffer, "%f", &fuel);
            if(fuel<0.0f)
            {
                printf("Invalid fuel: enter a non negative number\n");
                rettest=0;
            }

        }while(rettest!=1);

        planes[invent]->fuel=fuel;

    }
}

头文件是:

#ifndef PLANES_H_INCLUDED
#define PLANES_H_INCLUDED

typedef struct
{
    char letter;
    int number;
}model;


typedef struct
{
    int airplaneID;
    model planemodel;
    float fuel;
}plane;

void readPlanes(plane**, int*);
int lowestFuel(plane*, int);
void printID(plane*, int, char*);


#endif // PLANES_H_INCLUDED

无论如何,当我使用 planes=1 运行程序时,程序运行没有问题。但是,如果我尝试使用 2 个或更多平面运行它,则会出现以下错误(在程序结束时,用户输入所有平面的所有参数后):

检测到堆栈破坏:/home/user/Documents/program/bin/Debug/program 已终止 中止(核心转储)

我不知道为什么会这样,也不知道我的问题在哪里。有人能帮我吗?

最佳答案

给定 planes 声明为 plane **,此分配不正确:

*planes=(plane*)calloc((*size), sizeof(plane*));

您正在分配内存,plane * 将指向该内存;由于您将内存视为数组的存储,因此数组的元素(例如 (*planes)[0])必须是 plane 类型。但是,您没有为 plane 类型的 *size 元素分配足够的空间;只够那么多指针

用于分配的一种好的形式根据分配分配的指针指定所需的大小;例如,

mytype *p;
p = calloc(n, sizeof (*p));

观察分配的大小是根据 p 指向的事物的大小来定义的,这几乎总是你想要的,无需硬编码 p 的类型。这不仅减少了错误的范围,而且在更改 p 的类型方面也很灵活。 (另请注意,在 C 中转换 malloc/calloc/realloc 的结果不仅没有必要,而且被许多人认为是糟糕的形式。 )

在你的例子中,你分配的指针是*planes,所以上面的形式将实现为

*planes = calloc(*size, sizeof(**planes));

但是,您似乎对双指针感到困惑。这样做的唯一原因是使 readPlanes() 能够修改其调用者的局部变量。它并不意味着需要多级分配。特别是,分配内存并在 *planes 中记录指向它的指针后,随后分配更多内存并将其分配给 planes[0] 毫无意义,< em>这是一回事。然而,尝试将任何东西分配给 planes[1] 更没有意义,因为在调用此函数时,planes 指向 main的指针 planes,因此 planes[1] 指向一个 plane* 过去,到...什么?它没有定义,因此您的程序表现出未定义的行为。那是你的堆栈粉碎。

事实上,您根本不需要循环中的分配——您已经(在第一次更正之后)分配了您需要的所有空间。因为您将指针分配给了 *planes,所以您需要通过该指针访问它;这意味着使用 (*planes)[n] 形式的表达式来引用 nth 平面。例如,

(*planes)[invent].airplaneID = airplaneID;

关于c - 检测到堆栈粉碎 : running program with dinamically allocated array of structures,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43720384/

相关文章:

c - 简单计数器在 C 中不起作用

sorting - `take n (sort xs)` ("sorted prefix") 问题的内存高效算法

c - 结构对字体大小的贡献

c++ - 我应该如何在 typedef 中定义一组位数?

c - int 数组在末尾显示一个奇数

c - 减少 C 中的 If 语句

c - 如何有效地将三角矩阵存储在内存中?

r - R中整数向量的大小

c - 与结构内仅一个成员进行 union 的目的

c - 根据现有代码定义正确的结构