3

I've a problem with the fwrite function (I checked it using debugging on C::B). This is the code:

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);
    }
}

I receive an Segmentation Fault when fwrite is called. I can't understand where is the problem. I checked the fwrite prototype and I think it's all right.

Thank you in advance.

Jay
  • 9,585
  • 6
  • 49
  • 72
Federico Cuozzo
  • 363
  • 1
  • 7
  • 20

2 Answers2

1

Your compiler (e.g VC10 @alk) does not understand the 'h' in format specifiers which, which I believe, is a C99 addition. 3 solutions:

  1. Change to a new compiler.

  2. Read the short via a temporary variable.

    int i;
    scanf("%d", &i);
    Dati.Superati = i;
    
  3. Make the 2 fields int rather than short and use "%d"

    struct  studente {
       ...
       int Superati;
       int Crediti;
    } 
    ...
    scanf("%d", &Dati.Superati);
    ...
    scanf("%d", &Dati.Crediti);
    

Other minor suggestions:

// @ 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
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    Good call. That's what I was thinking. The `scanf` into the final field, Crediti, is stomping on `fp` which likely appears immediately after Crediti in the stack frame. – Colin D Bennett Sep 11 '14 at 16:58
0

Probably what is happening is this:

A call to fgets() or scanf() is storing data beyond the structure Dati. This stomps on the fp pointer variable, which is likely stored immediately after Dati on the stack frame. Then you call fwrite() which dereferences fp and boom you have undefined behavior and a segmentation fault.

I bet if you comment out all scanf and fgets functions that store into Dati and replace them with hard-coded assignments to Dati fields, you'll see that the crash is fixed.

Colin D Bennett
  • 11,294
  • 5
  • 49
  • 66