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

C语言程序出现Segmentation Fault,i/j/k值超出数组范围求助

C语言程序段错误(Segmentation Fault)排查与修复

问题概述

编写的C语言程序旨在从datospersonas.txt文件读取包含年龄(edad)、分数(notas)、性别(sexo)的结构体数据,进行统计分析时触发Segmentation Fault错误。通过打印索引变量i、j、k的值,发现这些值超出了数组定义的范围,这是导致崩溃的直接原因。手动创建测试文件后问题仍未解决,原程序及数据生成程序代码如下。


原主程序代码

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

int i = 0, j = 0, k = 0;

struct persona {
    int edad; //EDAD DE 12-65//
    int notas; //NOTAS DE 0-10//
    char sexo; //SEXO 1=MASCULINO Y 2=FEMENINO//
    char exi; //EXI 1=SI 2=NO
};

struct reg {
    int notas;
    int contex;
    int cont;
};

struct reg A[7][6][3];



int grupoedad(struct persona p) {
    if( p.edad < 12) {
        printf("\nexiste un error en la edad");
    } else if(p.edad < 16) {
        return 1;
    } else if(p.edad < 26) {
        return 2;
    } else if(p.edad < 36) {
        return 3;
    } else if(p.edad < 46) {
        return 4;
    } else if(p.edad < 56) {
        return 5;
    } else if(p.edad < 66) {
        return 6;
    }
}

int niveling(struct persona p) {
    if(p.notas < 2) {
        return 1;
    } else if(p.notas < 4) {
        return 2;
    } else if(p.notas < 6) {
        return 3;
    } else if(p.notas < 8) {
        return 4;
    } else if(p.notas <=10) {
        return 5;
    }
}

int femasc(struct persona p) {
    if(p.sexo == 'M'){
        return 1;
    } else if(p.sexo == 'F') {
        return 2;
    }
}

void etario(int j, char grupoed[10]) //ASIGNAMOS LOS RANGOS ETARIOS//
{
    switch(j)
    {
        case(1):
            strcpy(grupoed, "12-15");
            break;
        case(2):
            strcpy(grupoed, "16-25");
            break;
        case(3):
            strcpy(grupoed, "26-35");
            break;
        case(4):
            strcpy(grupoed, "36-45");
            break;
        case(5):
            strcpy(grupoed, "46-55");
            break;
        case(6):
            strcpy(grupoed, "56-65");
        default:
            printf("\nHa ocurrido un error");
    }
}

//void matrizcero(struct reg A[7][6][3], int i, int j, int k) {
   // for (i = 1; i < 7; i++)
   // {
        //for (j = 1; j < 6; j++)
      //  {
        //    for (k = 1; k < 3; k++)
          //  {
            //    A[i][j][k].contex = 0;
              //  A[i][j][k].cont = 0;
                //A[i][j][k].notas = 0;
           // }
       // }
  //  }
// }

int main() {
    struct reg {
    int notas;
    int contex;
    int cont;
    };

    struct reg A[7][6][3];
    struct persona p;   
    int rangomay, rangomen, rangointmay, resmay, resmen, jex, jmay, jmen, NIV, GRUPOET, sexo, cantidadM, califM, cantidadF, califF, grupoetario;
    // matrizcero(A[7][6][3], i, j, k);
    char grupoed[10];
    float prom_m, prom_f;

    FILE *entrada; //ABRO ARCHIVO
    entrada=fopen("datospersonas.txt","ab");
    if (entrada == NULL){
        exit(1);
        printf("\nError al abrir el archivo");
    }
    else {
        printf("\nArchivo abierto exitosamente!");
    }

    while(!(feof(entrada)))
    {
        fread(&p,sizeof(p),1,entrada);
        // void niveling(struct persona p, int i);
        // grupoedad(struct persona p, int j);
        // femasc(struct persona p, int k);
        i = niveling(p);
        j = grupoedad(p);
        k = femasc(p);

        printf("\n%d",i);
        printf("\n%d",j);
        printf("\n%d",k);

        A[i][j][k].notas = A[i][j][k].notas + p.notas;
        A[i][j][k].cont = A[i][j][k].cont;
        if(p.exi = 'S') {
            A[i][j][k].contex = A[i][j][k].contex + 1;
        }
    }

    for(i = 0; i < 5; i++) { //TOTALIZO HOMBRES Y MUJERES
        for(j = 0; j < 6; j++) {
            A[i][j][3].notas = A[i][j][3].notas + A[i][j][2].notas;
            A[i][j][3].cont = A[i][j][3].cont + A[i][j][2].cont;
            A[i][j][3].contex = A[i][j][3].contex + A[i][j][2].contex;
        }
    }

    for(j = 0; j < 6; j++) {
        for(i = 0; i < 5; i++) {
            cantidadM = cantidadM + A[i][j][1].cont;
            califM = califM + A[i][j][1].notas;
        }
    }

    prom_m = califM / cantidadM; //PROMEDIO DE CALIFICACIONES DE LOS HOMBRES

    for(j = 0; j < 6; j++) {
        for(i = 0; i < 5; i++) {
            cantidadF = cantidadF + A[i][j][2].cont;
            califF = califF + A[i][j][2].notas;
        }
    }

    prom_f = califF / cantidadM; //PROMEDIO DE CALIFICACIONES MUJERES

    for(k = 0; k < 2; k++) {
        for(i = 0; i < 5; i++) {
            for(j = 0; j < 6; j++) {
               A[6][j][k].cont = A[6][j][k].cont + A[i][j][k].cont;
               A[6][j][k].contex = A[6][j][k].contex + A[i][j][k].cont;
               A[6][j][k].notas = A[6][j][k].notas + A[i][j][k].notas;
            }
        }
    }

    for(j = 0; j < 6; j++) {
        A[6][j][3].cont = A[6][j][1].cont + A[6][j][2].cont;
        A[6][j][3].cont = A[6][j][1].contex + A[6][j][2].contex;
        A[6][j][3].notas = A[6][j][1].notas + A[6][j][2].notas;
    }
    
    resmay = A[6][1][3].contex;
    for(j = 0; j < 6; j++) {
        if(A[6][j][3].contex > resmay) {
            resmay = A[6][j][3].contex;
            jex = j;
        }
    }

    for(j = 0; j < 6; j++) {
        for(k = 0; k < 3; k++) {
            A[7][j][k].notas = A[6][j][k].notas / A[6][j][k].cont;
        }
    }

    resmen = A[7][1][3].notas;
    resmay = A[7][1][3].notas;
    for(j = 0; j < 6; j++) {
        if(A[7][j][3].notas > resmay) {
            resmay = A[7][j][3].notas;
            jmay = j;
        }
        else {
            if(A[7][j][3].notas < resmen) {
                resmen = A[7][j][3].notas;
                jmen = j;
            }
        }
    }

    etario(jmay, grupoed);
    printf("\nEl rango etario con mayor calificacion en promedio fue el comprendido entre: %s%s", grupoed, " años");
    etario(jmen, grupoed);
    printf("\nEl rango etario con menor calificacion en promedio fue el comprendido entre: %s%s", grupoed, " años");
    printf("\nEl promedio de calificaciones en femeninos fue: %f", prom_f);
    printf("\nEl promedio de calificaciones en masculinos fue: %f", prom_m);
    etario(jex, grupoed);
    printf("\nEl rango etario con mayor interes en rendir examenes internacionales es el comprendido entre: %s", grupoed, "años");

    fclose(entrada);
    system("pause");
    return 0;
}

原数据生成程序代码

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

struct persona {
    int edad; //EDAD DE 12-65//
    int notas; //NOTAS DE 0-10//
    char sexo; //SEXO 1=MASCULINO Y 2=FEMENINO//
    char exi; //EXI 1=SI 2=NO
};

void generacion()
{
    FILE *entrada;
    entrada=fopen("datospersonas.txt","ab");
    if (entrada == NULL){
        exit(1);
    }
    fclose(entrada);
}

int main()
{
    int s;
    int exi;
    generacion();
    persona p;
    FILE* entrada;
    entrada=fopen("datospersonas.txt","ab");
    srand(time(NULL));

        for (size_t i=0;i<650; i++)
        {
            p.edad =(rand() %54)+12;
            p.notas =(rand() %10)+1;
            s=(rand() %2)+1;
            if(s == 1){
                p.sexo='M';
            }
            else{
                p.sexo='F';
            }
            exi=(rand() %2)+1;
            if(exi == 1){
                p.exi='S';
            }
            else{
                p.exi='N';
            }
            fwrite(&p, sizeof(struct persona),1,entrada);
            printf("edad: %d\n",p.edad);
            printf("nota: %d\n",p.notas);
            printf("sexo: %c\n",p.sexo);
            printf("esta interesado en rendir examenes internacionales: %c\n",p.exi);
        }
        fclose(entrada);
        return 0;
}

核心问题分析

程序崩溃的根源是数组索引越界,但存在多个触发该问题的前置错误:

  • 索引规则不匹配:数组A[7][6][3]采用0-based索引(有效范围0-6、0-5、0-2),但grupoedad返回1-6,niveling返回1-5,femasc返回1-2,直接导致索引越界。
  • 函数无默认返回值:grupoedad、niveling、femasc在输入不符合条件时未返回值,会返回垃圾值作为索引,进一步加剧越界风险。
  • 文件打开模式错误:主程序用"ab"(追加二进制)模式打开要读取的文件,应使用"rb"(只读二进制)模式。
  • 未初始化变量:cantidadM、califM等统计变量未初始化,数组A未清零,导致统计结果异常或垃圾值干扰。
  • feof使用错误:while(!feof(entrada))会导致多读一次无效数据,触发对非法结构体的索引计算。
  • 赋值/比较混淆:if(p.exi = 'S')是赋值操作而非比较,会强制修改p.exi的值并始终为真。
  • 数组越界访问:多处出现A[i][j][3](第三维最大索引为2)、A[7][j][k](第一维最大索引为6)的非法访问。

修复方案

针对上述问题逐一修正:

1. 统一索引为0-based

修改三个索引函数,返回符合数组范围的0-based值:

  • grupoedad返回0-5(对应原1-6的年龄组)
  • niveling返回0-4(对应原1-5的分数段)
  • femasc返回0-1(对应原1-2的性别)

2. 给函数添加默认返回值

在每个索引函数末尾添加默认返回值,处理异常输入(如年龄<12、分数超出范围等)。

3. 修正文件打开模式

主程序中修改fopen参数为"rb",确保以只读模式打开文件。

4. 初始化变量与数组

  • 初始化统计变量cantidadM、califM等为0
  • 用循环或memset初始化数组A的所有成员为0

5. 修正文件读取逻辑

用fread的返回值判断是否读取成功,替代feof:

while(fread(&p, sizeof(p), 1, entrada) == 1)

6. 修正赋值/比较错误

将if(p.exi = 'S')改为if(p.exi == 'S')。

7. 修正数组越界访问

  • 删除所有A[i][j][3]的访问,调整统计逻辑到合法索引范围内
  • 删除A[7][j][k]的访问,改用合法的第一维索引存储平均值

修正后的主程序代码

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <string.h>

struct persona {
    int edad; // EDAD DE 12-65
    int notas; // NOTAS DE 0-10
    char sexo; // SEXO M=MASCULINO F=FEMENINO
    char exi; // EXI S=SI N=NO
};

struct reg {
    int notas;
    int contex;
    int cont;
};

// 调整数组大小以支持性别合计(第三维增加到3:0=M,1=F,2=合计)
struct reg A[6][6][3]; // 分数段0-4,年龄组0-5,性别0-2

int grupoedad(struct persona p) {
    if(p.edad < 12 || p.edad >65) {
        printf("\nError en edad: %d", p.edad);
        return 0; // 默认返回第一个年龄组
    } else if(p.edad < 16) {
        return 0;
    } else if(p.edad < 26) {
        return 1;
    } else if(p.edad < 36) {
        return 2;
    } else if(p.edad < 46) {
        return 3;
    } else if(p.edad < 56) {
        return 4;
    } else { // 56-65
        return 5;
    }
}

int
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 08:45:35