【问题标题】:Why is this program gives a segmentation fault?为什么这个程序给出了分段错误?
【发布时间】:2021-09-22 21:24:29
【问题描述】:

我正在做一些结构练习,但我无法理解分段错误。 我已经完成了几乎所有事情,分段错误在循环 for(i = 0;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);
        }

    }
}

【问题讨论】:

  • 你认为p[1].namep[1].l_name指向什么?
  • victor 0x3E7, sizeof(p[i].name) 可能是 4 或 8,而不是 50。
  • @chux-ReinstateMonica 为什么是 4 或 8 而不是 50?
  • p-&gt;namep[0].name 相同。所以你为第一个人的名字分配了内存,但你从来没有为第二个人分配任何东西。
  • @victor0x3E7 最好的。取决于编码目标。简单的修复,尝试fgets(p[i].name, MAX ,stdin) 并分配给p[1].name 等。

标签: c for-loop segmentation-fault initialization dynamic-memory-allocation


【解决方案1】:

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

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 )){

【讨论】:

  • sizeof(char) 定义为1,所以sizeof(char) * 可以在任何地方省略。然后是sizeof(p[i].name) 的问题是指针的大小,而不是它指向的分配的大小。
【解决方案2】:

代码未能分配给所有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);
}

如果您的库中没有 strdup() 的示例。

【讨论】:

    猜你喜欢
    • 2014-03-31
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    • 2018-04-12
    • 2019-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多