【问题标题】:What's the cause of my segmentation fault?我的分段错误的原因是什么?
【发布时间】:2010-09-22 05:15:35
【问题描述】:

我正在尝试编写一个程序,该程序使用输入重定向将文件中的条目读入动态分配的结构数组中。我的程序编译得很好,但我遇到了分段错误,我很难找到原因。

这是我的程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct StudentData
{
char* name;
char* major;
double gpa;
} Student;

int main()
{
Student* data = (Student*)malloc(sizeof(Student)*5);

int i;
for(i = 0; i < 5; i++)
{
 // allocate memory for name and read input
 data[i].name = malloc(50);
 *(data+i)->name == scanf("%s", (char*)&data[i].name);

 // allocate memory for major and read input
 data[i].major = malloc(30);
 *(data+i)->major == scanf("%s", (char*)&data[i].major);

 // read input for gpa
 (data+i)->gpa == scanf("%lf", &data[i].gpa); 

 //print array
 printf("%s\n%s\n%f\n", data[i].name, data[i].major, data[i].gpa);
 }
}  

有什么线索吗?如果这看起来很明显,那是因为我对 C 比较陌生!

【问题讨论】:

    标签: c arrays segmentation-fault structure


    【解决方案1】:

    这一行:

    *(data+i)->name == scanf("%s", (char*)&data[i].name);
    

    暂时忽略奇怪而空洞的==&amp;data[i].name 是错误的,因为您正在获取指针的地址。 data[i].name 在这里就足够了,因为 name 字段已经是 scanf 可以写入的地址。

    而对(char*) 的强制转换可能是关闭编译器的原因 - 您是否为此输入了它:-)?因为&amp;data[i].name 具有char** 类型,scanf 不会接受该类型,除非您将其强制转换为char*

    作为一般建议,尽量避免使用scanf - 它会导致非常不安全的代码(如您所见!)相反,使用fgets 读取一行(也从标准输入)然后中断这条线变成了它的成分。这最初可能需要更多的代码来实现,但会产生更安全和更可预测的代码。

    【讨论】:

    • 我会定义的。从现在开始坚持使用 fgets。感谢您及时的回复。我刚才学到了很多。真的很感激。
    • @Adam:不要到处乱扔演员来关闭编译器。如果您收到警告,那几乎肯定是有充分理由的;演员表应该谨慎使用,并且只有在你真的知道你为什么要这样做的情况下。
    【解决方案2】:
    *(data+i)->name == scanf("%s", (char*)&data[i].name);
    

    你比较scanf的返回值是为了什么?只需删除第一部分。另外,data[i].name 已经是一个指针,所以你不应该再次获取地址。它应该是:

    scanf("%s", data[i].name);  // no & because name is already a pointer
    

    同样:

    scanf("%s", data[i].major);
    scanf("%lf", &data[i].gpa);  // & here because gpa is just a double
    

    【讨论】:

    • 我现在感觉自己像个无知的人,但这对我帮助很大。程序现在像魅力一样运行。谢谢一百万。
    【解决方案3】:

    scanf 使用了一些不必要的代码,例如*(data+i)-&gt;name ==。这没有任何用处(并且可能导致段错误)。如果它没有导致访问错误,它会将 scanf 的返回值与指针进行比较,然后忽略比较的结果。 (一个体面的编译器会警告这一点。)

    去掉多余的代码后,技术上是没问题的,只是没有什么可以防止缓冲区溢出。这可以通过控制输入数据或添加对字符串长度的限制来完成,例如scanf("%50s", data[i].name);

    【讨论】:

    • 不确定我对 == 的看法。感谢您指出了这一点。程序现在运行良好。非常感谢。
    • 我在 scanf 参数列表中删除了多余的&amp;.name 已经是指向数据的指针;这里的&符号也会引起问题。即把输入的字符写入到name字段指针所在的数据结构中。
    【解决方案4】:

    &amp;data[i].name&amp;data[i].major 的类型为 char **,因此您不能安全地将其转换为 char *

    丢失与号将纠正您的错误。

    在使用 scanf() 时还存在其他逻辑错误,但这可能会让人不知所措 - 如果您在输入超过 50 个字符的名称后重新访问此代码,那就太好了。

    【讨论】:

    • 我不明白为什么编译器将它识别为 char**。现在这是有道理的。非常感谢。
    猜你喜欢
    • 2013-06-16
    • 1970-01-01
    • 2013-07-19
    • 2021-04-09
    • 2011-01-19
    • 2011-07-12
    • 1970-01-01
    • 2012-01-11
    • 1970-01-01
    相关资源
    最近更新 更多