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

C语言结构体使用malloc引发Segmentation Fault问题求助

你的C程序段错误及内存问题分析与修复

核心错误点分析

  • 循环内重复分配内存,数据彻底丢失:main函数的do-while循环里,每次都会执行emp* e = malloc(10*sizeof(emp));,这意味着每次循环都会拿到一块全新的内存,之前输入的员工数据会被直接丢弃,而且旧内存块没释放,还会造成内存泄漏。当你选择打印时,访问的是新分配的未初始化内存,必然触发段错误。
  • malloc内存大小计算错误:分配name和state时用了sizeof(char*),这是指针的大小(32位系统4字节,64位8字节),正确应该用sizeof(char)——因为你要分配的是字符数组空间,每个char占1字节。虽然这个错误不一定直接引发段错误,但属于逻辑漏洞。
  • printEmp函数printf参数错误:%d格式符需要传入int类型的值,但你传的是&e[i].date.day这类地址(指针),属于类型不匹配的未定义行为,偶然输出“正确”值只是巧合,本质会导致内存访问异常。

修正后的代码

#include<stdio.h>
#include<stdlib.h>

typedef struct Dob{
    int day;
    int month;
    int year;
}dob;

typedef struct Address{
    int h_num;
    int zip;
    char* state;
}address;

typedef struct employee{
    char* name;
    dob date;
    address ad;
}emp;

void enterEmp(emp* e,int i){
    // 修正malloc大小:用sizeof(char),或直接写30(char占1字节)
    e[i].name = malloc(30 * sizeof(char));
    if (!e[i].name) { // 增加内存分配失败判断
        perror("malloc failed for name");
        exit(1);
    }
    printf("Enter name : ");
    scanf("%s",e[i].name);
    printf("Enter dob in dd/mm/yy format : ");
    scanf("%d %d %d",&e[i].date.day,&e[i].date.month,&e[i].date.year);
    printf("Enter house number and zip code : ");
    scanf("%d %d",&e[i].ad.h_num,&e[i].ad.zip);
    printf("Enter state : ");
    e[i].ad.state = malloc(20 * sizeof(char));
    if (!e[i].ad.state) { // 增加内存分配失败判断
        perror("malloc failed for state");
        exit(1);
    }
    scanf("%s",e[i].ad.state);

    printf("\n Name : %s Date: %d/%d/%d Address- h-no: %d zip: %d state: %s \n",
           e[i].name,e[i].date.day,e[i].date.month,e[i].date.year,
           e[i].ad.h_num,e[i].ad.zip,e[i].ad.state);
}

void printEmp(emp *e,int len){
    int i;
    for(i=0;i<len;i++){
        // 修正printf参数:去掉&,直接传变量值
        printf("\n Name : %s Date: %d/%d/%d Address- h-no: %d zip: %d state: %s \n",
               e[i].name,e[i].date.day,e[i].date.month,e[i].date.year,
               e[i].ad.h_num,e[i].ad.zip,e[i].ad.state);
    }
}

// 新增内存释放函数,避免泄漏
void freeEmp(emp* e, int len) {
    for (int i = 0; i < len; i++) {
        free(e[i].name);
        free(e[i].ad.state);
    }
    free(e);
}

int main(){
    int choice;
    int len = 0;
    // 把内存分配移到循环外,只分配一次
    emp* e = malloc(10*sizeof(emp));
    if (!e) { // 检查数组内存分配是否成功
        perror("malloc failed for employee array");
        exit(1);
    }
    do{
        printf("\nEnter choice (1)Enter Employee (2)Read Employee (3)Exit : ");
        scanf("%d",&choice);
        switch(choice){
        case 1:
            if (len >=10) { // 限制最大员工数,避免数组越界
                printf("Maximum 10 employees allowed\n");
                break;
            }
            enterEmp(e,len);
            len++;
            break;
        case 2:
            if (len ==0) { // 无数据时提示
                printf("No employee data to display\n");
                break;
            }
            printEmp(e,len);
            break;
        case 3:
            freeEmp(e, len); // 退出前释放所有内存
            exit(0);
            break;
        default:
            printf("Invalid Input\n");
            break;
        }
    }while(1);
    return 0;
}

额外优化说明

  • 增加内存分配失败检查:malloc可能返回NULL,必须判断,否则会引发段错误;
  • 新增内存释放逻辑:退出前释放所有动态分配的内存,避免内存泄漏;
  • 增加数组上限判断:防止输入超过10个员工导致数组越界访问;
  • 无数据打印提示:避免空输出的尴尬。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:15:40