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