为什么这个程序会出现段错误?

Why is this program gives a segmentation fault?

我正在做一些结构练习,我无法理解分段错误。 我几乎一切都做对了,分段错误在循环中 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);
        }

    }
}

您声明了一个包含两个元素的数组

person p[2];

而且你只初始化了第一个元素的数据成员p[0]

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

以上语句等同于

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

第二个元素 p[1] 的数据成员未初始化且具有不确定的值。

因此,当您尝试使用数组第二个元素的这些未初始化数据成员时,for 循环会调用未定义的行为,例如

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

此外,您在 fgets

的调用中使用了错误的表达式
sizeof(p[i].name)

数据成员name(还有l_name)是一个指针。所以上面的表达式将产生一个指针的大小。

相反,您只需要写 MAX,例如

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

代码无法为所有p[i].name分配。

传递给 fgets() 的尺寸错误。

考虑在阅读后分配。读入本地缓冲区,然后形成大小合适的副本。

for(i = 0; i<2; i++) {
  char buf[MAX + 2];

  if (fgets(buf, sizeof buf, stdin)) {
        fprintf(stderr,"Error reading string");
        exit(2);
    }
  buf[strcspn(buf, "\n")] = 0; // Lop off potential \n
  p[i].name = strdup(buf);     // Common, but non-standard string allocation

  if (fgets(buf, sizeof buf, stdin)) {
        fprintf(stderr,"Error reading string");
        exit(3);
    }
  buf[strcspn(buf, "\n")] = 0;
  p[i].lname = strdup(buf);
}

如果您的图书馆中没有,请示例