【发布时间】:2016-05-22 19:37:33
【问题描述】:
我正在尝试创建一个程序来读取文件并创建一个结构数组,其中填充了文件中的数据。问题是当我运行它时,我有时会得到一个“调试断言失败!”错误表达式:_CtrlsValidHeapPointer(block),有时不会有问题,有时Visual Studio调试器会这样说: ConsoleApplication6.exe 中 0x775C1B45 (ntdll.dll) 处未处理的异常:0xC0000005:访问冲突读取位置 0x0040D510。
这是我的代码:
#include <stdio.h>
#define SIZE 256
struct Record {
char * firstName;
char * lastName;
char * address;
char * city;
char * state;
int * zipCode;
int * phoneNumber;
};
void initializeRecord(struct Record * list, char * lineOfText, int i);
void makeList(char * lineOfText, struct Record * list, int * psize);
int main(void) {
char lineOfText[SIZE];
int size = 0;
int * psize = &size;
struct Record * list = malloc(sizeof(struct Record));
makeList(lineOfText, list, psize);
free(list);
}
void makeList(char * lineOfText, struct Record * list, int * psize)
{
FILE * fp = fopen("myfile.txt", "r");
while (fgets(lineOfText, SIZE, fp)) {
list = realloc(list, sizeof(struct Record) + (*psize)*sizeof(struct Record));
initializeRecord(list, lineOfText, *psize);
(*psize)++;
}
fclose(fp);
}
void initializeRecord(struct Record * list, char * lineOfText, int i) {
char * newline = strchr(lineOfText, '\n');
if (newline)
*newline = 0;
char * firstName = strtok(lineOfText, "\t");
list[i].firstName = malloc(strlen(firstName)+1);
strcpy(list[i].firstName, firstName);
list[i].firstName[strlen(firstName) + 1] = '\0';
char *lastName = strtok(NULL, "\t");
list[i].lastName = malloc(strlen(lastName)+1);
strcpy(list[i].lastName, lastName);
list[i].lastName[strlen(lastName) + 1] = '\0';
char *address = strtok(NULL, "\t");
list[i].address = malloc(strlen(address)+1);
strcpy(list[i].address, address);
list[i].address[strlen(address) + 1] = '\0';
char *city = strtok(NULL, "\t");
list[i].city = malloc(strlen(city)+1);
strcpy(list[i].city, city);
list[i].city[strlen(address) + 1] = '\0';
char *state = strtok(NULL, "\t");
list[i].state = malloc(strlen(state)+1);
strcpy(list[i].state, state);
list[i].state[strlen(address) + 1] = '\0';
int *zipCode = strtok(NULL, "\t");
list[i].zipCode = malloc(strlen(zipCode)*sizeof(int)+1);
strcpy(list[i].zipCode, zipCode);
list[i].zipCode[strlen(zipCode)] = '\0';
int *phoneNumber = strtok(NULL, "\t");
list[i].phoneNumber = malloc(strlen(phoneNumber)*sizeof(int)+1);
strcpy(list[i].phoneNumber, phoneNumber);
list[i].phoneNumber[strlen(phoneNumber)] = '\0';
}
这是一个示例文件(除了中间不应该有全新的行,每个元素之间应该有制表符,我只是看不到如何在 StackOverflow 上格式化):
玛丽·琼斯 6201 Wioewjife Ave DOHfeo Hills AZ 93321 2465551234
比利鲍勃 7290 DIowhoefh St Uwopufeoi NY 23311 2345552393
约翰·琼斯 1234 EWOHFklfsh St WEDhofehif CA 98304 2345551238
马克·乔 2398 Yeiofejp Blvd Hdeefoidjs MT 13210 4355553973
我的猜测是我的问题是,当我为数组分配空间时,我没有分配足够的空间,因为 sizeof(struct Record) 可能不足以存储我要复制的内容,但我不知道如何创造足够的空间。
【问题讨论】:
-
您为
strcpy包含的'\0'终止符分配了足够的内存,但随后list[i].firstName[strlen(firstName) + 1] = '\0';不必要地写入了另一个终止符,超出了数组边界。 -
将 API
void makeList(char * lineOfText, struct Record * list, int * psize);更改为void makeList(char * lineOfText, struct Record ** list, int * psize); -
是时候结交使用调试器的朋友了。如果不能舒适地调试,就无法完成 C 编程。由于这里的控制流很简单,因此请专注于数据,我相信您会很快看到您的问题。
-
另外,不要在每个函数中多次使用
strlen(),除非在函数执行期间字符串的长度发生了变化。实际上,在您的情况下,最好 1. 使用strdup()。 2. 如果您使用的环境没有strdup()或等效项,请编写一个简单的strdup()函数以避免重复。 -
@George 请不要编辑代码中的错误。想想看——你最终会没有问题要回答,读者也不知道这些 cmets 和答案是关于什么的。
标签: c arrays pointers memory malloc