从二进制分段错误中读取时

时间:2019-11-21 17:04:47

标签: c

我有2个文件,分别是creator.c和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文件创建一个名为save.bin的二进制文件,并将person结构数据推送为二进制文件, reader.c从该文件读取并打印此人的名字,但是此代码出现了段错误,我错过了什么呢?

2 个答案:

答案 0 :(得分:3)

write不会写所指事物的值。它将写入指针。读取时,您会读取指针,但是它们无效。

要么将namekind声明为固定大小的数组,要么分别写入它们的值,然后在读取它们之前不要忘记分配新的内存。

编辑:最好先写下名称的长度,然后准确读取该长度,因为可以跟随更多的记录。

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

答案 1 :(得分:1)

此代码:

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

...从文件中读取Person结构。

这段代码:

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

..尝试访问Person.name指向的内存。

但是它指向什么呢? name包含您从文件中读取的内存地址,但尚未为该名称分配内存。您正在读取该地址处的内存,但是该地址不再是有效的内存地址。当您尝试访问无效的内存时,您会遇到分段错误。

有几种处理方法,但是最简单的方法是将名称存储在同一块内存中。您可以这样做:

#define MAX_NAME 80

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

现在,读人也读名字。您还需要对kind做同样的事情,否则您将遇到同样的问题。