删除动态指针数组中单元格的正确方法

The right way to delete a cell in dynamic array of pointers

在我当前的作业项目中,我构建了一个动态指针数组,其中每个指针指向一个数据结构,其中包含一些字符串(表示用户)。我正在尝试找到正确的方法来删除数组中的特定单元格(或用户),而不会出现任何堆内存问题。

所以我一直在尝试 free 特定的单元格,然后移动其他单元格,这样就不会留下空单元格了。之后,我尝试 "cut" 当前为空的最后一个单元格,realloc 数组为 -1。请参阅我描述问题的代码中的注释。

User** deleteMale(User** pMaleArr, int *maleArrSize, User *onlineUser)
{
    int i,j;
    //for each array element check if the username matches to the 
    // connected user
    for (i = 0;i < *maleArrSize;i++)
    {
        if (strcmp(pMaleArr[i]->userName, onlineUser->userName) ==0) 
        {
            //when the user is found, free all fields of the struct
            freeUserFields(onlineUser);
            //check if it's the last array cell
            if (i != *maleArrSize - 1)
            {
                //shift cells
                for (j = i;j < *maleArrSize;j++)
                {
                    pMaleArr[j] = pMaleArr[j + 1];

                }//free the last cell
                free(pMaleArr[*maleArrSize-1]); //I'm getting a problem here because now the 2 last cells of the array have the same pointer adress.
            }
            //remove the last cell
            pMaleArr = (User **)realloc(pMaleArr, (*maleArrSize 
- 1)*sizeof(User*));
            if (pMaleArr == NULL)
            {
                if (*maleArrSize != 1)
                {
                    printf(MA_FAILED);
                    exit(1);
                }
            }
            break;
        }
    }
    *maleArrSize -= 1;
    return pMaleArr;
}

void freeUserFields(User *person)
{
    if (person != NULL)
    {
        //free all fields
        free(person->firstName);
        free(person->lastName);
        free(person->age);
        free(person->userName);
        free(person->userPassword);
        free(person->about);
        free(person->hobbies);
        //free node itself
        free(person);
    }

}

所以正如我在上面注意到的,当我尝试 free 最后一个单元格时,为了之后删除它,它也删除了 (last-1) 单元格,因为我复制了他们的地址。在这种情况下,我找不到另一种移动单元格的方法。我可以获得有关如何正确处理它的建议吗? 谢谢!

您不应该释放最后一个单元格,因为您保留了指向该用户的指针。

只需删除第二个免费的。

此外,第二个循环应该达到 j < *maleArrSize -1

我已经在您的代码中添加了注释,希望这对您有所帮助:

     //check if it's the last array cell
        if (i != *maleArrSize - 1)
        {
            //shift cells
            for (j = i;j < *maleArrSize-1;j++)
            {
                pMaleArr[j] = pMaleArr[j + 1];/* you need till size -1 because of[j+1]*/

            }//free the last cell
            free(pMaleArr[*maleArrSize-1]); //I'm getting a problem here because now the 2 last cells of the array have the same pointer adress.
        }
        //remove the last cell- here if the cell to remove was the last one you don't free its inner allocations.
        pMaleArr = (User **)realloc(pMaleArr, (*maleArrSize 

这段代码存在严重问题:

    if (strcmp(pMaleArr[i]->userName, onlineUser->userName) ==0) 
    {
        //when the user is found, free all fields of the struct
        freeUserFields(onlineUser);                  // NOOO !!!

您正在释放传递给控制用户名的结构上的字段,而您应该只访问 *pMaleArr 数组的内容。你应该写:

    if (strcmp(pMaleArr[i]->userName, onlineUser->userName) ==0) 
    {
        //when the user is found, free all fields of the struct
        freeUserFields(pMaleArr[i]);

而且你不应该释放最后一个单元格。您不释放指针,而是释放它指向的位置。 last 指针指向的内容现在由 previous 指针指向并且必须保留。所以其他部分应该是:

        if (i != *maleArrSize - 1)
        {
            //shift cells
            for (j = i;j < *maleArrSize;j++)
            {
                pMaleArr[j] = pMaleArr[j + 1];

            }//just ignore the last cell
        }