You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态指针数组元素删除的正确方法及堆内存问题求助

解决动态指针数组删除元素时的重复释放与越界问题

看起来你的问题出在移位逻辑错误和释放对象错误上,我来帮你一步步修正:

问题根源分析

  1. 释放了错误的对象:你调用freeUserFields(onlineUser),但实际上要删除的是数组中存储的pMaleArr[i](堆上分配的用户结构体),onlineUser只是用来匹配的参考对象,不该被释放。
  2. 移位循环越界且逻辑错误:你的移位循环for (j = i;j < *maleArrSize;j++)会导致j+1超出数组边界(当j等于*maleArrSize-1时,j+1就是数组的长度,属于越界访问),而且移位后最后两个元素的指针会重复,这时候再释放pMaleArr[*maleArrSize-1]就等于重复释放了倒数第二个元素,触发内存错误。
  3. 多余的释放操作:移位后不需要手动释放最后一个元素,因为我们后续会通过realloc缩小数组,直接丢弃那个重复的指针即可。

修正后的代码实现

User** deleteMale(User** pMaleArr, int *maleArrSize, User *onlineUser) {
    int i,j;
    //遍历数组元素,检查用户名是否与在线用户匹配
    for (i = 0;i < *maleArrSize;i++) {
        if (strcmp(pMaleArr[i]->userName, onlineUser->userName) == 0) {
            // 1. 释放数组中找到的目标用户结构体(这才是堆上的对象)
            freeUserFields(pMaleArr[i]);
            
            // 2. 如果不是最后一个元素,将后续元素向前移位
            if (i != *maleArrSize - 1) {
                // 循环条件改为j < *maleArrSize - 1,避免j+1越界
                for (j = i; j < *maleArrSize - 1; j++) {
                    pMaleArr[j] = pMaleArr[j + 1];
                }
            }
            
            // 3. 重新分配数组内存,缩小一个元素的大小
            User** newArr = (User**)realloc(pMaleArr, (*maleArrSize - 1)*sizeof(User*));
            if (newArr == NULL) {
                printf(MA_FAILED);
                exit(1);
            }
            pMaleArr = newArr;
            
            // 4. 调整数组大小并退出循环
            *maleArrSize -= 1;
            break;
        }
    }
    return pMaleArr;
}

void freeUserFields(User *person) {
    if (person != NULL) {
        // 按顺序释放所有字符串字段
        free(person->firstName);
        free(person->lastName);
        free(person->age);
        free(person->userName);
        free(person->userPassword);
        free(person->about);
        free(person->hobbies);
        // 最后释放结构体本身
        free(person);
    }
}

关键修正点说明

  • 释放正确对象:现在我们释放的是pMaleArr[i],也就是数组中存储的堆分配用户结构体,而不是传入的onlineUser。
  • 修复移位循环:循环条件改为j < *maleArrSize - 1,确保j+1不会超出数组的有效索引范围,移位后只会让数组最后一个位置的指针与倒数第二个重复,但我们后续会通过realloc丢弃这个位置。
  • 安全处理realloc:将realloc的结果赋值给临时指针newArr,避免原指针在分配失败时丢失(如果直接赋值给pMaleArr,分配失败会导致原内存地址丢失,造成内存泄漏)。
  • 移除多余的释放:不再手动释放pMaleArr[*maleArrSize-1],因为realloc会自动处理数组大小的调整,那个重复的指针会被丢弃,而对应的用户对象已经被保留在数组的前*maleArrSize-1个位置中。

这样修改后,就能正确删除指定用户,避免重复释放和越界访问的问题啦!

内容的提问来源于stack exchange,提问作者Boris Erlich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:44:23