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

C语言struct中char数组长度≥30时调用add函数后程序崩溃如何解决

问题产生原因
  • 核心根源是栈上可变长度数组(VLA)越界访问:你在main函数中定义的struct Data emp[n]是长度固定为n的栈上数组,仅能容纳n个员工数据。但add函数中直接将n加5后,向emp[n]到emp[n+4]的非法地址写入数据,属于未定义行为。
    • 当结构体char数组长度为20及以下时,结构体整体占用空间小,越界写入的内容暂时没有覆盖栈上的函数返回地址、栈帧基址等关键内存,所以程序看起来可以正常运行;
    • 当结构体char数组长度大于等于30时,结构体整体占用空间变大,越界写入的内容直接破坏了栈上的关键数据,导致add函数执行完循环准备返回/调用display时触发内存访问错误,程序直接崩溃。
  • 额外存在两个风险代码:
    1. fflush(stdin)是C标准未定义行为,仅部分编译器支持该用法,无法保证跨平台正常清理输入缓冲区;
    2. gets函数已经被C标准完全废弃,该函数不检查输入长度,极易触发缓冲区溢出。
修复方案
  1. 替换栈上VLA为动态分配内存:使用malloc初始化员工数组,需要新增数据时用realloc扩容,从根本上解决数组越界问题。
  2. 替换风险函数:删掉fflush(stdin),改用fgets替代gets读取字符串,输入后手动清理缓冲区残留的换行符。
  3. 调整add函数逻辑:需要将扩容后的数组地址和新的长度返回给主调函数。

关键修改代码示例

主函数初始化部分修改:

int main(void)
{
    int n;
    int a;
    printf("enter the number of employees:\n");
    scanf("%d", &n);
    // 改用动态内存分配
    struct Data *emp = malloc(n * sizeof(struct Data));
    if(emp == NULL) {
        printf("内存分配失败\n");
        return 1;
    }
    input(emp, n);
    printf("enter the operation you want to perform:\n");
    printf("1 - to find employee record from employee id\n");
    printf("2 - to sort employee record on basis of employee id\n");
    printf("3 - to alphabetically sort array of characters\n");
    printf("4 - to count the number of employees in database\n");
    printf("5 - to add 5 more records\n");
    scanf("%d", &a);
    switch (a)
    {
    case 1:
        find(emp, n);
        break;
    case 2:
        sortid(emp, n);
        display(emp, n);
        break;
    case 3:
        sortAlp(emp, n);
        display(emp, n);
        break;
    case 4:
        count(emp, n);
        break;
    case 5:
        // 接收add返回的新地址,n传指针修改原值
        emp = add(emp, &n);
        break;
    }
    // 最后释放内存
    free(emp);
    return 0;
}

add函数修改:

struct Data* add(struct Data *emp, int *n)
{
    // 扩容数组
    *n += 5;
    struct Data *temp = realloc(emp, (*n) * sizeof(struct Data));
    if(temp == NULL) {
        printf("扩容失败\n");
        return emp;
    }
    emp = temp;
    for (int i = *n - 5; i < *n; i++)
    {
        printf("enter employee id of %d employee: \n", i + 1);
        scanf("%d", &emp[i].Emp_id);
        // 清理输入缓冲区残留换行
        while(getchar() != '\n');
        printf("enter employee name of %d employee: \n", i + 1);
        fgets(emp[i].Emp_name, sizeof(emp[i].Emp_name), stdin);
        // 去掉fgets读取的末尾换行
        emp[i].Emp_name[strcspn(emp[i].Emp_name, "\n")] = '\0';
        printf("enter employee city of %d employee: \n", i + 1);
        fgets(emp[i].Emp_city, sizeof(emp[i].Emp_city), stdin);
        emp[i].Emp_city[strcspn(emp[i].Emp_city, "\n")] = '\0';
    }
    display(emp, *n);
    return emp;
}

其他修改:

同步将input函数中的gets和fflush(stdin)也按照上面的方式替换即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:18:03