【问题标题】:segmentation fault while malloc linked listmalloc 链表时出现分段错误
【发布时间】:2019-05-10 16:18:05
【问题描述】:

我创建了两个结构:

typedef struct Student{
    int id; 
    char* name;
    int birthYear;
    int finishedCourses;
    int courseCredits;
    double avarage;
    int coursesNow;
    NodeCourses* courses;

}Student;

typedef struct NodeS{
    Student student;
    struct NodeS* next;
}NodeS;

所以我现在可以创建学生的链接列表。

我想做的一件事是让用户输入每个学生的详细信息。

所以我创建了一个名为“addNewStudent”的函数

首先在函数中这样做:

NodeS* newStudent;
    newStudent=(NodeS*)malloc(sizeof(NodeS));

然后,当我要求用户插入一个名称时,我将它放在一个名为“name”的字符串中,并且我想再次 malloc 名称字符串。 所以我这样做:

newStudent->student.name=(char*)malloc(sizeof(char)*strlen(name));

那条线给了我分段错误。

ps: 我已经检查了字符串是否在写入大小内,并且我得到的是正确的。

我该怎么办?

【问题讨论】:

  • 附带说明,请参阅此问题的顶部答案:stackoverflow.com/questions/605845/…
  • 另外,假设您正在做看起来正在做的事情,您想分配sizeof(char) * (strlen(name) + 1),为空终止符留出空间。
  • 如果该行给你一个错误,你一定是早先做了一些导致未定义行为的事情,并且它破坏了堆。这可能是因为您没有将名称长度加 1,因此创建以前的学生导致缓冲区溢出。
  • 我们需要更多地了解您的程序以了解您的所有问题。
  • 请展示你的put it in a string called "name"

标签: c segmentation-fault


【解决方案1】:
 newStudent->student.name=(char*)malloc(sizeof(char)*strlen(name));

我相信你的话,这行代码会导致分段错误。这行代码做了三件事,其中任何一件都可能是你的原因:

1) 你做strlen(name)。如果name 没有指向具有正确 nul 终止字节的有效 C 样式字符串,则可能会出现段错误。你可以通过在代码行之前添加这个来测试这个理论:

printf("About to call strlen\n");
printf("Got: %d\n", strlen(name));

如果这是问题所在,您将看到第一行输出,但看不到第二行,因为段错误会在程序有机会执行之前终止程序。

2) 你打电话给malloc。由于先前的双重释放、释放后使用、缓冲区溢出或类似问题,堆可能已损坏。所以对malloc 的调用可能是先前损坏的受害者。您可以通过添加以下代码来测试:

printf("About to call strlen\n");
printf("Got: %d\n", strlen(name));
printf("About to call malloc\n");
char *o = malloc(sizeof(char) * strlen(name));
printf("Malloc didn't segfault\n");
newStudent->student.name=o;

3) 您分配给newStudent->student.name。例如,如果 newStudentNULL 或不指向有效内容,那可能是您的问题。您可以通过添加以下代码来测试:

printf("About to call strlen\n");
printf("Got: %d\n", strlen(name));
printf("About to call malloc\n");
char *o = malloc(sizeof(char) * strlen(name));
printf("Malloc didn't segfault\n");
printf("Trying to access newStudent->student.name\n");
printf("newStudent->student.name=%p\n", newStudent->student.name);
newStudent->student.name=o;
printf("Actually, the whole statement worked\n");

如果您看到所有的printfs,但您的程序仍然崩溃,那么您对导致段错误的语句有误。

【讨论】:

  • 我们可以合理地确定他将名称复制到这样测量的缓冲区中,因此丢弃了堆。崩溃在下一次调用相同的故障行时再次出现并非不合理。这只是时间问题......
猜你喜欢
  • 2017-06-06
  • 2021-03-18
  • 1970-01-01
  • 2017-11-21
  • 1970-01-01
  • 2015-05-18
  • 2017-11-24
  • 1970-01-01
相关资源
最近更新 更多