C 检测到堆栈崩溃:正在使用随机分配的结构数组运行程序
我正在编写以下程序:C 检测到堆栈崩溃:正在使用随机分配的结构数组运行程序,c,memory-management,struct,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; re
#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;
}
}
无论如何,当我用planes=1运行程序时,程序运行没有问题。但是,如果我尝试使用2个或更多平面运行它,则会发生以下错误(在程序结束时,在用户输入所有平面的所有参数后):
检测到堆栈崩溃:/home/user/Documents/program/bin/Debug/program terminated
中止(堆芯转储)
我不知道为什么会发生这种情况,我的问题在哪里。有人能帮我吗 给定声明为
平面**
的平面,此分配不正确:
*planes=(plane*)calloc((*size), sizeof(plane*));
您正在分配平面*
将指向的内存;由于您将内存视为阵列的存储器,因此阵列的元素(例如,(*planes)[0]
)必须为plane
类型。但是,您没有为*大小类型平面的元素分配足够的空间;只够这么多的指针
用于分配的良好表单根据分配所指向的指针指定所需的大小;比如说,
mytype *p;
p = calloc(n, sizeof (*p));
(*planes)[invent].airplaneID = airplaneID;
请注意,分配的大小是根据p
指向的对象的大小定义的,这几乎总是您想要的,而无需硬编码p
的类型。这不仅减少了错误的范围,而且对于p
类型的更改也很灵活。(还需要注意的是,在C语言中转换malloc
/calloc
/realloc
的结果不仅是不必要的,而且被许多人视为糟糕的形式。)
在您的情况下,您正在为其分配的指针是*平面
,因此上述形式将实现为
*planes = calloc(*size, sizeof(**planes));
然而,你似乎被双指针弄糊涂了。唯一的原因是启用readPlanes()
来修改其调用者的局部变量。这并不意味着需要多层次的分配。特别是,在分配了内存并在*平面中记录了指向它的指针之后,随后分配更多内存并将其分配给平面[0]
是没有意义的,这是同样的事情。然而,尝试将任何内容分配给平面[1]
的意义就更小了,因为调用此函数时,平面
指向主
的指针平面
,因此平面[1]
指向一个平面*
。。。什么?它没有定义,因此您的程序表现出未定义的行为。那是你的一塌糊涂
事实上,您根本不需要循环中的分配——您已经(在第一次更正之后)分配了所需的所有空间。因为您将指针指定给*平面
,所以您希望通过该指针访问它;这意味着使用形式为(*planes)[n]
的表达式来引用n
th平面。比如说,
mytype *p;
p = calloc(n, sizeof (*p));
(*planes)[invent].airplaneID = airplaneID;
标准C没有C++STL意义上的“向量”。看起来您想要的术语可能是“数组”。嗯,free(planes)
不会释放您分配的所有内容,因此理论上这里存在内存泄漏。但这可能与你看到的错误无关。嗨,约翰·布林格!非常感谢您的回复。我理解你对内存分配的解释。但是,关于双指针以及为什么使用它,我仍然有一些问题。是因为您可能希望readPlanes更改平面数组(平面*)的地址吗?如果我们的数组没有被动态分配,我们只需要一个指针(当然,表示向量)吗?谢谢@GrangerObliviate,我已经说明了使用双指针的原因(尽管它是您的程序——您还不知道为什么要这样做吗?)。唯一合理的原因是函数readPlanes()
可以设置属于调用者的变量的值,因为调用者通过传递指向该(指针)变量的指针进行合作。