如何在C语言中正确动态分配结构体以避免段错误?
通讯录程序动态分配结构体出现Segmentation fault错误
我在开发一款通讯录程序时,动态分配结构体遇到了问题,程序运行出现 Segmentation fault (core dumped) 错误。以下是相关代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct contact{ int number; char name[80]; }contact; void addContact(contact **contacts, int position){ int aux=position; printf("Enter the name: "); setbuf(stdin, 0); fgets(contacts[position]->name,80,stdin); printf("Enter the telephone number: "); scanf("%d",&contacts[position]->number); return; } void printAllContacts(contact **contacts, int size){ for(int i;i<size;i++){ printf("Contact %d:\n",i); printf("Name: %s\n",contacts[i]->name); printf("Telephone number: %d \n",contacts[i]->number); } } // Main function: int main(){ int size; printf("Enter the list size: "); scanf("%d",&size); contact *contacts= (contact*)malloc(sizeof(contact)*size); int counter=0; int x; do{ printf("------------MENU-----------\n"); printf("1-Add contact\n"); printf("2-Print contacts list\n"); printf("0-Exit\n"); printf("----------------------------\n"); printf("Enter an option: "); scanf("%d",&x); switch (x){ case 1: addContact(&contacts,counter); counter++; break; case 2: printAllContacts(&contacts,counter); break; case 0: break; } }while(x!=0); return 0; }
请问有人能帮忙解决吗?
错误原因分析
- 指针类型不匹配:
main中contacts是指向结构体数组的一级指针,但你传递给函数的是二级指针&contacts。函数内用contacts[position]->name会直接访问二级指针偏移后的非法地址,触发段错误。 - 循环变量未初始化:
printAllContacts里的for循环中i未初始化,初始值随机,会导致循环行为不可预测,可能越界访问内存。 - 输入缓冲区处理不当:
scanf读取整数后留下的换行符会被后续fgets直接读取,导致姓名输入为空,setbuf(stdin, 0)不是可靠的清空方式。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct contact{ int number; char name[80]; }contact; void addContact(contact *contacts, int position){ printf("Enter the name: "); // 清空scanf残留的换行符 int c; while((c = getchar()) != '\n' && c != EOF); fgets(contacts[position].name, 80, stdin); // 移除fgets读取的换行符 contacts[position].name[strcspn(contacts[position].name, "\n")] = '\0'; printf("Enter the telephone number: "); scanf("%d", &contacts[position].number); } void printAllContacts(contact *contacts, int size){ for(int i = 0; i < size; i++){ printf("Contact %d:\n", i); printf("Name: %s\n", contacts[i].name); printf("Telephone number: %d \n", contacts[i].number); } } int main(){ int size; printf("Enter the list size: "); scanf("%d", &size); contact *contacts = (contact*)malloc(sizeof(contact)*size); // 检查内存分配是否成功 if(contacts == NULL){ printf("Memory allocation failed!\n"); return 1; } int counter = 0; int x; do{ printf("------------MENU-----------\n"); printf("1-Add contact\n"); printf("2-Print contacts list\n"); printf("0-Exit\n"); printf("----------------------------\n"); printf("Enter an option: "); scanf("%d", &x); switch (x){ case 1: // 检查是否超出通讯录容量 if(counter >= size){ printf("Contact list is full!\n"); break; } addContact(contacts, counter); counter++; break; case 2: printAllContacts(contacts, counter); break; case 0: break; default: printf("Invalid option!\n"); } }while(x != 0); // 释放动态分配的内存 free(contacts); return 0; }
关键修正说明
- 函数参数改为一级指针
contact*,直接传递结构体数组地址,用.运算符访问成员 - 初始化循环变量
i=0,避免随机值导致的异常 - 用
while(getchar())可靠清空输入缓冲区,解决scanf与fgets的输入冲突 - 添加内存分配成功检查、通讯录容量判断,避免非法访问
- 释放动态内存,避免内存泄漏
- 移除
fgets读取的换行符,优化姓名显示效果
内容的提问来源于stack exchange,提问作者brazuka
相关产品推荐
相关产品推荐

