C 分段故障w/fwrite

C 分段故障w/fwrite,c,segmentation-fault,fwrite,C,Segmentation Fault,Fwrite,我对fwrite函数有问题(我在C::B上使用调试检查了它)。 代码如下: struct studente { char Cognome_Nome[30]; char Matricola [11]; short Superati; float Media_Pesata; short Crediti; }; typedef struct studente STUDENTE; void main() { FILE *fp; STUDENTE Dat

我对
fwrite
函数有问题(我在C::B上使用调试检查了它)。 代码如下:

struct  studente
{   char Cognome_Nome[30];
    char Matricola [11];
    short Superati;
    float Media_Pesata;
    short Crediti;
};
typedef struct studente STUDENTE;

void main()
{   FILE *fp;
    STUDENTE Dati;

    if((fp = fopen("studente.dat","w+b")) == NULL)
        printf("Error\n");
    else
    {   fflush(stdin);
        printf("Inserire il cognome e nome: ");
        fgets(Dati.Cognome_Nome, 30, stdin);

        fflush(stdin);
        printf("\nInserire la matricola: ");
        fgets(Dati.Matricola, 11, stdin);

        fflush(stdin);
        printf("Inserire il numero di esami superati: ");
        scanf("%hd", &Dati.Superati);

        fflush(stdin);
        printf("Inserire la media pesata: ");
        scanf("%f", &Dati.Media_Pesata);

        fflush(stdin);
        printf("Inserire il numero di crediti: ");
        scanf("%hd", &Dati.Crediti);

        fwrite(&Dati, sizeof(STUDENTE), 1, fp);
    }
}
调用
fwrite
时,我收到一个分段错误。我不明白问题出在哪里。我检查了
fwrite
原型,我觉得没问题


提前谢谢。

可能发生的情况是:

调用
fgets()
scanf()
将数据存储在结构
Dati
之外。这将踩踏
fp
指针变量,该变量很可能存储在堆栈帧上的
Dati
之后。然后调用
fwrite()
,该函数将取消引用
fp
,并显示未定义的行为和分段错误

我敢打赌,如果你注释掉所有存储在
Dati
中的
scanf
fgets
函数,并将它们替换为
Dati
字段的硬编码赋值,你会发现崩溃已经修复。

你的编译器(例如VC10@alk)不理解格式说明符中的
'h'
,我相信,是一个C99添加。3种解决方案:

  • 更改为新编译器

  • 通过临时变量读取
    short

    int i;
    scanf("%d", &i);
    Dati.Superati = i;
    
  • 将两个字段设置为
    int
    而不是
    short
    ,并使用
    %d


  • 其他次要建议:

    // @ Tom Tanner
    // void main()
    int main(void)
    
    // Avoid magic numbers
    // fgets(Dati.Cognome_Nome, 30, stdin);
    fgets(Dati.Cognome_Nome, sizeof Dati.Cognome_Nome, stdin);
    
    // @ Jeyaram
    // Do not use fflush(stdin). Better methods exist to handle stray input data
    // fflush(stdin);
    
    // Less error prone and easier to maintain code
    // fwrite(&Dati, sizeof(STUDENTE), 1, fp);
    fwrite(&Dati, sizeof Dati, 1, fp);
    
    // Check I/O function results
    

    请参考以下讨论,可能您的系统很旧,不理解
    %h..“
    中的
    'h'
    ?什么操作系统?@Jeyaram我用fflush()只是为了尝试。我使用了一个在web上找到的_fflush()函数@chux我使用Windows 8,但在上一个Ubuntu中,代码不起作用。您是否已经完成了
    #include.h>
    ?否则可能会发生奇怪的事情。另外,它应该是
    int main
    ,但这不太可能导致您的问题。@ralph它可能会有帮助,但
    size\t fwrite(const void*restrict ptr、size\t size、size\t nmemb、FILE*restrict stream)
    nmemb
    元素,其大小由
    size
    指定)和OP似乎正确调用了它。对于样式:我建议
    fwrite(&Dati,sizeof Dati,1,fp),但这不是这里的主要问题。您在考虑哪个
    fgets()
    scanf()
    ?它们在我看来都很好,我认为它们很好。但我敢打赌,
    fp
    被人踩了,这是我唯一认为有可能发生的事情。打得好。我就是这么想的。最后一个字段Crediti中的
    scanf
    正在跺踏
    fp
    ,该字段很可能在堆栈帧中Crediti之后立即出现。
    // @ Tom Tanner
    // void main()
    int main(void)
    
    // Avoid magic numbers
    // fgets(Dati.Cognome_Nome, 30, stdin);
    fgets(Dati.Cognome_Nome, sizeof Dati.Cognome_Nome, stdin);
    
    // @ Jeyaram
    // Do not use fflush(stdin). Better methods exist to handle stray input data
    // fflush(stdin);
    
    // Less error prone and easier to maintain code
    // fwrite(&Dati, sizeof(STUDENTE), 1, fp);
    fwrite(&Dati, sizeof Dati, 1, fp);
    
    // Check I/O function results