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

Malloc调用在第二次执行时崩溃的原因排查求助

程序循环调用时第二次崩溃的原因分析

问题背景

程序需返回指向内存中学生对象的指针数组,首次运行正常,但在循环3次调用该操作的场景中,第二次运行时在malloc行崩溃,编译器未给出报错信息。

相关代码

目标函数getMyStudentBySize

Student **getMyStudentBySize(Student *allStudent, int wantSize,
                             int maxsize, Teacher *pteacher) {      
    int counter = 0;
        
    Student **myStudent = (Student **)malloc(1 * sizeof(Student *));
    for (int i = 0; i < MAX_TOTAL_STUDENT; i++) {
        for (int h = 0; h < NUMBER_OF_CLASSES; h++) {
            if (allStudent[i].myClassRoom) {
                if (strcmp(allStudent[i].myTeachers[h]->name,
                           (char *)pteacher->name) == 0) {
                    myStudent[counter++] = &allStudent[i];
                    break;
                }
            } else
                break;
        }
    }
    return myStudent;
}

调用函数assignTeacher

void assignTeacher(Teacher **teacherArray, ClassRoom **allClassRooms,
                   Student *allStudents) {
    int mySize = helperAssignTeacher(allStudents, *teacherArray, NULL);
    Student **myStudentFor = getMyStudentBySize(allStudents, mySize,
                                 allClassRooms[chooseClassRoom - 1]->maxSize,
                                 ((*teacherArray) + (chooseTeacher - 1)));
    printAllStudent(myStudentFor, allClassRooms[chooseClassRoom - 1]->maxSize);
}

崩溃发生在第二次执行getMyStudentBySize时的这行代码:

Student **myStudent = (Student **)malloc(1 * sizeof(Student *));

崩溃原因分析

  • 堆内存损坏:getMyStudentBySize中仅分配了1个Student*的内存空间,但后续循环中counter会随着找到符合条件的学生而递增,当学生数量超过1时,myStudent[counter++]会写入超出分配范围的内存,直接破坏堆结构。第一次调用可能因堆损坏未被立即检测到而正常运行,但堆已处于异常状态,第二次调用malloc时,堆管理器检测到损坏就会触发崩溃。
  • 参数未合理利用:函数参数wantSize和maxsize完全未被使用,这两个参数本应用来提前计算并分配足够的内存空间,却被忽略,导致内存分配不足。
  • 空指针解引用风险:代码中直接访问allStudent[i].myTeachers[h]->name,未检查allStudent[i].myTeachers[h]是否为空,若该指针为空会触发未定义行为,可能间接破坏内存。另外,pteacher->name被强制转换为char*,如果原类型并非char*,会导致字符串比较时的内存访问错误。
  • 内存泄漏:getMyStudentBySize返回的指针数组在assignTeacher中使用后未被free,多次调用会累积内存泄漏,长期运行可能耗尽内存,也可能间接影响堆的稳定性。

修复方案

  1. 按需分配足够内存:先统计符合条件的学生数量,再分配对应大小的内存,避免越界:
Student **getMyStudentBySize(Student *allStudent, int wantSize,
                             int maxsize, Teacher *pteacher) {      
    int counter = 0;
    // 第一步:统计符合条件的学生数量
    for (int i = 0; i < MAX_TOTAL_STUDENT; i++) {
        if (!allStudent[i].myClassRoom) {
            break;
        }
        for (int h = 0; h < NUMBER_OF_CLASSES; h++) {
            if (allStudent[i].myTeachers[h] && 
                strcmp(allStudent[i].myTeachers[h]->name, pteacher->name) == 0) {
                counter++;
                break;
            }
        }
    }
    // 分配对应数量的指针内存
    Student **myStudent = (Student **)malloc(counter * sizeof(Student *));
    if (!myStudent) {
        // 处理内存分配失败的情况
        return NULL;
    }
    // 第二步:填充学生指针
    counter = 0;
    for (int i = 0; i < MAX_TOTAL_STUDENT; i++) {
        if (!allStudent[i].myClassRoom) {
            break;
        }
        for (int h = 0; h < NUMBER_OF_CLASSES; h++) {
            if (allStudent[i].myTeachers[h] && 
                strcmp(allStudent[i].myTeachers[h]->name, pteacher->name) == 0) {
                myStudent[counter++] = &allStudent[i];
                break;
            }
        }
    }
    return myStudent;
}
  1. 添加空指针检查:访问指针成员前先判断指针是否为空,避免未定义行为。
  2. 释放内存:在assignTeacher中调用printAllStudent后,添加内存释放代码:
printAllStudent(myStudentFor, allClassRooms[chooseClassRoom - 1]->maxSize);
free(myStudentFor); // 释放分配的指针数组
  1. 移除不必要的强制转换:确保pteacher->name本身就是char*类型,若类型不匹配需修正定义,而非强制转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 02:06:32