Search code examples
cfor-loopsegmentation-faultinitializationdynamic-memory-allocation

Why is this program gives a segmentation fault?


I was doing some struct exercises and I can't understand the segmentation fault. I've done almost everything all right, the segmentation fault is on the loop for(i = 0;i<2;i++)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<stdint.h>
#define MAX 50
int main(void)
{
    typedef struct {
        char *name;
        char *l_name;
        u_int32_t age;
    }person;
    u_int32_t i;
    person p[2];
    p->name = (char *) malloc(sizeof(char) * MAX);
    p->l_name = (char *) malloc(sizeof(char)* MAX);

    if(p->name == NULL || p->l_name == NULL){
        fprintf(stderr,"Error allocating memory");
        exit(1);
    }

    for(i = 0;i<2;i++){
        if(!fgets(p[i].name,sizeof(p[i].name),stdin)){
            fprintf(stderr,"Error reading string");
            exit(2);
        }
        if(!fgets(p[i].l_name,sizeof(p[i].l_name),stdin)){
            fprintf(stderr,"Error reading string");
            exit(3);
        }

    }
}


Solution

  • You declared an array of two elements

    person p[2];
    

    And you initialized data members only of the first element p[0]

    p->name = (char *) malloc(sizeof(char) * MAX);
    p->l_name = (char *) malloc(sizeof(char)* MAX);
    

    The above statements are equivalent to

    p[0].name = (char *) malloc(sizeof(char) * MAX);
    p[0].l_name = (char *) malloc(sizeof(char)* MAX);
    

    Data members of the second element p[1] are not initialized and have indeterminate values.

    So the for loop invokes undefined behavior when you are trying to use these uninitialized data members of the second element of the array as for example

    if(!fgets(p[i].name,sizeof(p[i].name),stdin)){
    

    And moreover you are using an incorrect expression in the call of fgets

    sizeof(p[i].name)
    

    Data member name (and also l_name) is a pointer. So the above expression will yield the size of a pointer.

    Instead you need to write just MAX as for example

    if(!fgets(p[i].name, MAX, stdin )){