c - 函数中的结构数组重新分配 - 产生未定义的行为
问题描述
我有一个包含 3 个字符指针(任意长度字符串)的结构,并且我使用 malloc 创建了一个动态数组,因为它可以有任意数量的条目。这是我的结构数据类型:
typedef struct student{
char* name;
char* phoneNumber;
char* department;
}STUDENT;
每当需要新条目时,我使用了一个函数来重新分配来增加结构数组的大小,并使用另一个函数来打印整个数组。
我遇到的问题是:我能够在 addNumber 函数中打印新条目,但是当我尝试在 addNumber 函数之外打印时,情况并非总是如此。有时它可以工作,大多数时候我遇到分段错误:11 和一次在添加新条目时我得到一个'malloc:对象 0x7fc426c058f0 的 *** 错误:未分配重新分配的指针'
这是我的主要内容:
int nEntry = 0;
STUDENT* directory = malloc(nEntry * sizeof *directory);
if(directory == NULL){
puts("Unable to allocate memory");
exit(-1);
}
while(1){
int choice = 0;
scanf("%d", &choice);
while(getchar() != '\n');
switch(choice){
case 1:
printDirectory(directory, nEntry);
break;
case 2:
addNumber(directory, &nEntry);
break;
default:
printf("Unknown option!\n");
break;
}
}
return 0;
这是我的 addNumber 函数:
void addNumber(STUDENT* Array, int* nArray){
*nArray += 1;
int x = *nArray - 1;
STUDENT* tempDirectory = realloc(Array, *nArray * sizeof *Array);
if(tempDirectory == NULL){
puts("Unable to allocate memory");
exit(-1);
}
else{
Array = tempDirectory;
Array[x].name = (char*)malloc(sizeof(char*));
Array[x].phoneNumber = (char*)malloc(sizeof(char*));
Array[x].department = (char*)malloc(sizeof(char*));
printf("Name: ");
scanf("%[^\n]", Array[x].name);
while(getchar() != '\n');
printf("Number: ");
scanf("%[^\n]", Array[x].phoneNumber);
while(getchar() != '\n');
printf("Department: ");
scanf("%[^\n]", Array[x].department);
while(getchar() != '\n');
for(int i = 0; i < *nArray; i++){
printf("%s\t%s\t(%s)\n", (Array + i)->name, (Array + i)->phoneNumber, (Array + i)->department);
}
}
}
这是我的打印功能:
void printDirectory(STUDENT* Array, int nArray){
int i;
for(i = 0; i < nArray; i++){
printf("%s\t%s\t(%s)\n", (Array + i)->name, (Array + i)->phoneNumber, (Array + i)->department);
}
}
如果我将条目硬编码到 main 中,打印功能可以正常工作,问题似乎是在 addNumber 函数中创建的内容没有正确传回?但是对于我通过引用传递的所有论点,我很困惑为什么我会得到一个未定义的行为。
解决方案
正如评论中所指出的,您malloc
的 s 大小错误,因此您的代码还有其他问题,但要解决您对 realloc 的具体担忧:
要存储 的返回值realloc
以便可以在主函数中访问它,您需要传递指针的地址。
所以主要是:
addNumber(&directory, &nEntry); // Note the ampersand
在 addNumber 中:
void addNumber(STUDENT** Array, int* nArray){ // Note the pointer to a pointer
...
STUDENT* tempDirectory = realloc(*Array, *nArray * sizeof *Array); // Note Array is dereferenced
...
*Array = tempDirectory;
...
如果您将directory
main 中的变量描述为存储在位置 0x1 并指向内存位置 0x2 的变量,那么在您当前的代码中,您将向函数发送 0x2。该函数可以在那里读取数据,但它没有引用 0x1 来更新directory
main 中的变量。
通过引用传递的一般规则是:如果要更新函数中的引用以便调用者可以读取它,则需要在传递它时使用比调用者中的变量多一个星号。所以如果你有一个int
in main,你会想要更新int*
函数中的一个。如果你有一个int***
in main,你会想要更新一个int****
.
推荐阅读
- amazon-web-services - 为什么 AWS ECS 有 10240 个 CPU 单元的限制?
- amazon-s3 - Lambda@Edge Cache-Control 标头不存在 Cloudfront
- r - R, sapply 似乎没有应用提供的功能
- typescript - 静态类的 TypeScript 索引器
- webpack-dev-server - 是否有在本地使用视频(.mov、.mp4)和带有“文件加载器”的 Webpack 的特殊配置?
- nosql - DynamoDB - 从分区键列表中获取对象的最有效/最便宜的方法?
- html - 将按钮定位在img两侧的中间高度
- javascript - 从 CircleMarker 扩展的标记 - 如何更改点击区域?
- hololens - 如何获取活动 MRTK 指针的位置?
- c - 为什么 free() 会把东西留在内存中?