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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 20:51:18