0

I have 2 files that are creator.c and reader.c

creator.c:

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

struct Person{
  char *name;
  int numb;
  char *kind;
};

int main() {

  struct Person *per1=malloc(sizeof(struct Person));
  struct Person *per2=malloc(sizeof(struct Person));
  struct Person *per3=malloc(sizeof(struct Person));
  struct Person *per4=malloc(sizeof(struct Person));
  struct Person *per5=malloc(sizeof(struct Person));
  struct Person *per6=malloc(sizeof(struct Person));

  char per1_name[]="a1";
  char per2_name[]="b1";
  char per3_name[]="c1";
  char per4_name[]="d1";
  char per5_name[]="e1";
  char per6_name[]="f1";

  per1->name=malloc(strlen(per1_name)+1);
  per2->name=malloc(strlen(per2_name)+1);
  per3->name=malloc(strlen(per3_name)+1);
  per4->name=malloc(strlen(per4_name)+1);
  per5->name=malloc(strlen(per5_name)+1);
  per6->name=malloc(strlen(per6_name)+1);

  strcpy(per1->name,per1_name);
  strcpy(per2->name,per2_name);
  strcpy(per3->name,per3_name);
  strcpy(per4->name,per4_name);
  strcpy(per5->name,per5_name);
  strcpy(per6->name,per6_name);

  per1->numb=1;
  per2->numb=2;
  per3->numb=3;
  per4->numb=4;
  per5->numb=5;
  per6->numb=6;


  char per1_kind[]="x";
  char per2_kind[]="y";
  char per3_kind[]="z";
  char per4_kind[]="q";
  char per5_kind[]="w";
  char per6_kind[]="e";

  per1->kind=malloc(strlen(per1_kind)+1);
  per2->kind=malloc(strlen(per2_kind)+1);
  per3->kind=malloc(strlen(per3_kind)+1);
  per4->kind=malloc(strlen(per4_kind)+1);
  per5->kind=malloc(strlen(per5_kind)+1);
  per6->kind=malloc(strlen(per6_kind)+1);

  strcpy(per1->kind,per1_kind);
  strcpy(per2->kind,per2_kind);
  strcpy(per3->kind,per3_kind);
  strcpy(per4->kind,per4_kind);
  strcpy(per5->kind,per5_kind);
  strcpy(per6->kind,per6_kind);



  FILE *write_ptr;
  write_ptr = fopen("save.bin","wb");
  fwrite(per1,sizeof(struct Person),1,write_ptr);
  fwrite(per2,sizeof(struct Person),1,write_ptr);
  fwrite(per3,sizeof(struct Person),1,write_ptr);
  fwrite(per4,sizeof(struct Person),1,write_ptr);
  fwrite(per5,sizeof(struct Person),1,write_ptr);
  fwrite(per6,sizeof(struct Person),1,write_ptr);


  return 0;
}

reader.c

#include <stdio.h>

struct Person{
  char *name;
  int numb;
  char *kind;
};

int main(){
  FILE *fp=fopen("./save.bin","rb");
  struct Person *person1=malloc(sizeof(struct Person));
  fread(person1,sizeof(struct Person),1,fp);
  printf("%s\n",person1->name );
}

creator.c file create a binary file called save.bin and push the person struct data as binary, reader.c read from that file and print the name of the person but this code getting segmentation fault, what is the point that i missed out?

4
  • 1
    Start with adding an error checking code for fopen. Commented Nov 21, 2019 at 17:06
  • i added printf("%p\n",fp ) after file pointer of reader.c and it gave me an adress is there any different problem because i have never access the data that is read. @EugeneSh. Commented Nov 21, 2019 at 17:11
  • You could save time for people who want to help by showing exactly where you are getting this error. Commented Nov 21, 2019 at 17:13
  • @JonathanWood i can not change my code above. The site did not permit the changes. The seg. fault block is fread(person1,sizeof(struct Person),1,fp); printf("%s\n",person1->name ); these two line can not access the data. Commented Nov 21, 2019 at 17:22

2 Answers 2

3

write does not write the values of the things pointed to. It will write the pointers. When you read, you read the pointers, but they are invalid.

Either declare name and kind as fixed-sized arrays, or write their values separately and then don't forget to malloc new memory before you read them.

EDIT: it is better to first write the length of the name and then read exactly that length, because more records can follow.

int main() {

  struct Person *per1=malloc(sizeof(struct Person));
  per1->name=malloc(strlen("hello")+1);
  strcpy(per1->name,"hello");

  FILE *write_ptr;
  write_ptr = fopen("save.bin","wb");
  fwrite(per1,sizeof(struct Person),1,write_ptr);
  int len= strlen(per1->name);
  fwrite(&len,sizeof(int), 1, write_ptr;   // first write the length
  fwrite(per1->name,len,1,write_ptr);      // then write those bytes
  fclose(write_ptr);                       // don't forget!
  return(0);
}
// reader
int main(){
  FILE *fp=fopen("./save.bin","rb");
  struct Person *person1=malloc(sizeof(struct Person));
  fread(person1,sizeof(struct Person),1,fp);
  int len;
  fread(&len,sizeof(int),1,fp);                // now read the length
  person1->name=malloc(len+1);                 // allocate memory for it,
  fread(person1->name,len,1,fp);               // read it
  person1->name[len]= '\0';                    // and terminate it
  printf("%s\n",person1->name );
}
Sign up to request clarification or add additional context in comments.

7 Comments

Can you explain with an example. I am new in c and i do not understand what i should do?
Thanks for your example.
@XY, use the latest version (had some bugs)
Nits - validations, but I presume those were intentionally omitted. (even the validation of fclose after-write).
@DavidRankin-ReinstateMonica, yes. Oversimplified. (P.s., what is with Monica?)
|
1

This code:

fread(person1,sizeof(struct Person),1,fp);

... reads a Person structure from the file.

And this code:

printf("%s\n",person1->name );

.. attempts to access the memory that Person.name points to.

But what does it point to? name contains a memory address that you read from the file, but no memory has been allocated for the name. You are reading the memory at that address but that address is no longer a valid memory address. And you get a segmentation fault when you attempt to access invalid memory.

There are several ways to deal with this but the easiest is to store the name in the same block of memory. You can do that like this:

#define MAX_NAME 80

struct Person{
  char name[MAX_NAME + 1];
  int numb;
  char *kind;
};

Now, reading the person also reads the name. You'll also need to do the same thing with kind or you'll have the same problem there.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.