VS在第二次重新分配后发疯

时间:2018-12-29 20:33:27

标签: c dynamic-memory-allocation realloc

所以我有一个输入文件,其中包含以下文本(每行=用户):

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;
            }

为什么会这样?我该怎么解决?谢谢!

2 个答案:

答案 0 :(得分:1)

此处:

head = &head[*menArraySize];

您指向的是新位置,但是您还会覆盖(丢失)head原始值(除非您减去)。当您这样做时:

head = &head[0];

认为,您正在恢复原始值,但是什么也做不了。您只需引用/取消引用相同的值即可。

解决方案:使用另一个User *temp值引用新位置。使用head后,请保持realloc不变。

答案 1 :(得分:0)

@Jean-François has covered the immediate bug。但是,将问题分解为定义明确的部分可以避免很多麻烦。

代码在做什么...

  1. 打开文件并从文件中读取一堆变量,然后调用另一个函数将这些变量转换为User并将其添加到列表中。
  2. 通过一堆变量构造一个User并将其推入数组。

当您描述函数“ and”时,可以将其分解为较小的函数。传递变量(awaithead)表示不必要地将两个单独的动作一起使用。最后需要传递成对的变量(menArraySizehead)表明也许应该将它们转换为结构。

相反,它应该像这样分开...

  1. 打开文件。
  2. 从文件中读取用户。
  3. 将用户推送到数组上。

这将导致两个更简单的功能以及更完善的功能。

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 *