对C中二进制文件写/读的误解

时间:2017-10-25 23:30:53

标签: c

有人可以在我从二进制文件中读取它后,每当我尝试对结构内部的任何一个字符数组做任何事情时,请解释为什么以下代码会出现段错误?代码如下:

struct my_struct {
    int filename_len;
    char *filename;
    int size;
    char *contents;
};

int main() {
    FILE *fp = fopen("test.bin", "wb");
    char *one = "list1";
    char *two = "test file";
    int one_len = strlen(one);
    int two_len = strlen(two);

    fwrite(&one_len, sizeof(int), 1, fp);
    fwrite(&one, one_len, 1, fp);
    fwrite(&two_len, sizeof(int), 1, fp);
    fwrite(&two, two_len, 1, fp);
    fclose(fp);



    struct x *temp = malloc(sizeof(struct x));
    fp = fopen("test.bin", "rb");

    fread(&(temp->filename_len), sizeof(int), 1, fp);
    fread(&(temp->filename), sizeof(char), temp->filename_len, fp);
    fread(&(temp->size), sizeof(int), 1, fp);
    fread(&(temp->contents), sizeof(char), temp->size, fp);

    // This  does not segfault
    printf("%d\n", temp->filename_len);

    // This does
   printf("%s\n", temp->filename);
   fclose(fp);

   return 0;
}

谢谢!

2 个答案:

答案 0 :(得分:2)

fwrite(&one, one_len, 1, fp);

&one是堆栈上指针 one的地址,而不是它指向的位置。这意味着,不是写one所指向的字符串,而是编写构成其地址的字节,可能还有在内存中发生的任何事情。

fread(&(temp->filename), sizeof(char), temp->filename_len, fp);

类似地,这会将指针(或指针的一部分)读入temp->filename,并可能另外覆盖其后发生的任何事情。

您需要做的是:

fwrite(one, one_len, 1, fp);

写出字符串的实际内容,而不是其地址。

temp->filename = calloc(temp->filename_len + 1, sizeof(char));
fread(temp->filename, sizeof(char), temp->filename_len, fp);

为文件名分配适当大小的缓冲区,然后将数据读入该缓冲区。

答案 1 :(得分:1)

1)您使用地址 fread致电temp->filename

fread(&(temp->filename), sizeof(char), temp->filename_len, fp)

你不想这样做。 temp->filename已经是指向char的指针。而只是传递temp->filename

2)您没有为temp->filename分配任何空间。阅读temp->filename_len后,您需要执行此操作。

fread(&(temp->filename_len), sizeof(int), 1, fp);
temp->filename = malloc((temp->filename_len + 1) * sizeof(char))
fread(temp->filename, sizeof(char), temp->filename_len, fp);
temp->filename[temp->filename_len] = '\0';

同样适用于temp->contents