cfread

fread second pass give segmentation fault


if i compile and execute the following code, all goes fine

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

int main()
{

FILE *FILE_LICENCE;
char* LICENCE_F = "Lc"; 
int RC; 
char* MSG = "Error";

struct Lic {
   int h;
   char* u;
} lic;
struct Tmp {
   int h;
   char* u;
} tmp;

    lic.h = 1234567;
    lic.u = "USER";
//    goto CC;
    FILE_LICENCE = fopen(LICENCE_F,"wb");
    RC = fwrite(&lic, sizeof(struct Lic), 1, FILE_LICENCE);
    if (RC !=1 ) {
        puts(MSG);
    }
    fclose(FILE_LICENCE);
//CC:
    FILE_LICENCE = fopen(LICENCE_F,"rb");
    RC = fread(&tmp, sizeof(struct Tmp), 1, FILE_LICENCE);
    if (RC !=1 ) {
        puts(MSG);
    }
    fclose(FILE_LICENCE);
    printf("%i\n",tmp.h);
    printf("%s\n",tmp.u);
    return 0;
}

i'm able to read tmp.h and tmp.u correctly now if i re-compile program using the goto CC; .. that means read directly the file, i get a segmentation fault at the last instruction

 printf("%s\n",tmp.u);

(you can easily re-produce the problem..) What's wrong ? Thanks in advance for the support Maurizio


Solution

  • You have two problems here.

    First, the structure type you're writing to disk and the type you're reading from disk are not the same. Even though the names and types of the members are the same, there's no guarantee that they can be used interchangeably. You should be using struct Lic for both.

    Second, the structure you're writing to disk contains a pointer. When you subsequently read that pointer back in from the same process that wrote it, the pointer value is still valid and can dereferenced. However when you write in one process and read in another, there's no guarantee that pointer value will be valid in the program that does the read. That's what's happening in your case which causes the crash.

    Change the structure type to contain an array of char instead of a pointer, that way what you read will be the same as what you wrote.

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    
    struct Lic {
       int h;
       char u[10];
    };
    
    int main()
    {
    
        FILE *FILE_LICENCE;
        char* LICENCE_F = "Lc";
        int RC;
        char* MSG = "Error";
    
        struct Lic lic, tmp;
    
        lic.h = 1234567;
        strcpy(lic.u,"USER");
        //goto CC;
        FILE_LICENCE = fopen(LICENCE_F,"wb");
        RC = fwrite(&lic, sizeof(struct Lic), 1, FILE_LICENCE);
        if (RC !=1 ) {
            puts(MSG);
        }
        fclose(FILE_LICENCE);
    //CC:
        FILE_LICENCE = fopen(LICENCE_F,"rb");
        RC = fread(&tmp, sizeof(struct Lic), 1, FILE_LICENCE);
        if (RC !=1 ) {
            puts(MSG);
        }
        fclose(FILE_LICENCE);
        printf("%i\n",tmp.h);
        printf("%s\n",tmp.u);
        return 0;
    }