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
相关产品推荐
相关产品推荐

