所以我有一个输入文件,其中包含以下文本(每行=用户):
012345678;danny;cohen;22;M;danny1993;123;1,2,4,8;Nice person
223325222;or;dan;25;M;ordan10;1234;3,5,6,7;Singer and dancer
349950234;nadav;cohen;50;M;nd50;nadav;3,6,7,8;Engineer very smart
首先,代码为一个用户分配空间,然后为另一个用户(每个用户)重新分配空间。事实是,一切顺利,直到第二次重新分配为止,然后它向我显示错误“ Exercise 6.exe触发了断点”。我还将首先提到错误: ““ wntdll.pdb未加载”,但我尝试执行VS建议的操作-带有符号的操作。然后出现“触发断点”错误。
我尝试切换文本文件中的行,但这没关系,问题是在第二次尝试重新分配后发生的。
让我向您展示代码的相关部分:
int main()
{
//intiallizing variables
int menArraySize = 0;
//creating a NULL array pointer (array) for men
User *head = NULL;
readInputFile(head, &menArraySize, list);
}
void readInputFile(User *head, int *menArraySize, WomenList *list)
{
//temporary data types for the the stracture we're creating
char id[10];
char *firstName = NULL;
char *lastName = NULL;
char age[4] = { 0 };
char gender = '\0';
char *userName = NULL;
char *password = NULL;
char hobbies = 0;
char *description = NULL;
//regular function data types
int i = 0, j = 0, k = 0, currentDetail = 1, size;
char currentString[212] = { 0 };
int currentChar;
//opening the input file
FILE *input = fopen("input.txt", "r");
...
//long code for allocating room for each string (firstName, lastName, etc...)- irelevant
...
head = addMale(head, menArraySize, id, firstName, lastName, age,
gender, userName, password, hobbies, description);
...
//rest of the function isn't relevant
}
User* addMale(User *head ,int *menArraySize, char id[], char *firstName,
char *lastName,char age[], char gender, char *userName,
char *password, char hobbies, char *description)
{
//if the array is empty, allocate room for one user
if (*menArraySize == 0)
{
head = (User *)malloc(1 * sizeof(User));
}
//if the array isn't empty, reallocate room for one more user
else
{
**this is the line in which the error occurs (second time reallocating,
third dynamic allocation total for this pointer)**
head = (User *)realloc(head, (*menArraySize + 1) * sizeof(User));
}
//if the allocation failed
if (head == NULL)
exit(1);
//pointing to the new user we created
head = &head[*menArraySize];
//apply all details to the user
strcpy(head->id, id);
head->firstName = firstName;
head->lastName = lastName;
strcpy(head->age, age);
head->gender = gender;
head->userName = userName;
head->password = password;
head->hobbies = hobbies;
head->description = description;
//applying an index number to the user
head->index = *menArraySize;
//pointing back to the head of the array
head = &head[0];
//updating the variable showing the size of the array
*menArraySize = *menArraySize + 1;
return head;
}
为什么会这样?我该怎么解决?谢谢!
答案 0 :(得分:1)
此处:
head = &head[*menArraySize];
您指向的是新位置,但是您还会覆盖(丢失)head
原始值(除非您减去)。当您这样做时:
head = &head[0];
您认为,您正在恢复原始值,但是什么也做不了。您只需引用/取消引用相同的值即可。
解决方案:使用另一个User *temp
值引用新位置。使用head
后,请保持realloc
不变。
答案 1 :(得分:0)
@Jean-François has covered the immediate bug。但是,将问题分解为定义明确的部分可以避免很多麻烦。
代码在做什么...
当您描述函数“ and”时,可以将其分解为较小的函数。传递变量(await
,head
)表示不必要地将两个单独的动作一起使用。最后需要传递成对的变量(menArraySize
和head
)表明也许应该将它们转换为结构。
相反,它应该像这样分开...
这将导致两个更简单的功能以及更完善的功能。
menArraySize
并像这样使用。
User *UserRead(FILE *fp);
void UsersPush(Users *users, User *user);
请注意,我还制作了一个Users结构来封装数组,数组的大小以及其中有多少用户。这样一来,我们就只传递了一个用户结构,即Users结构,而我们只需要处理数组工作即可。
FILE *input = fopen("input.txt", "r");
if( input == NULL ) {
perror("Could not open input.txt");
exit(1);
}
Users *users = UsersNew();
User *user = UserRead(input);
if( user == NULL ) {
fprintf(stderr, "Could not read user.\n");
exit(1);
}
UsersPush(users, user);
所有这些都可以替换为存储typedef struct {
// How many users?
size_t num;
// How much space do we have?
size_t size;
User **users;
} Users;
// Allocate and initialize Users.
Users *UsersNew() {
Users *users = malloc(sizeof(Users));
// Because we're storing the size separate from the number of users
// we can preallocate some space. This makes the code simpler, no NULL
// condition to worry about, and we can be smarter about growing the array.
users->num = 0;
users->size = 1;
users->users = malloc(sizeof(Users*));
return users;
}
// Isolate the tricky work of growing the array in its own function.
// This makes it reusable, and we can improve the growth algorithm.
void UsersGrowIfNecessary(Users *users) {
// asserts like these to check for impossible conditions will save you
// a lot of debugging time. This makes sure there's never more Users than
// space for them.
assert(users->size >= users->num );
// Check if we need more space.
if( users->size == users->num ) {
// Double the size to avoid excessive expensive reallocs.
size_t new_size = users->size * 2;
users->users = realloc(users->users, sizeof(Users*) * new_size);
users->size = new_size;
}
}
// Add the user, growing the array if necessary.
void UsersPush(Users *users, User *user) {
UsersGrowIfNecessary(users);
// With all that done, adding the user is simple.
users->users[users->num] = user;
users->num++;
}
的通用自增长数组。出于学习目的而自己实现它是很好的,但是对于任何严肃的代码,请抓住现有的实现。我喜欢GLib,因为它是通用的,有据可查,经过了很好的测试,并且具有许多其他功能。
在处理完所有这些之后,分配和读取用户的工作可以自己解决。
void *