Struct 将结构数组写入二进制文件

Struct 将结构数组写入二进制文件,struct,fwrite,fread,pointer-to-array,Struct,Fwrite,Fread,Pointer To Array,我不明白节目中有什么错误。我正在定义一个指向结构数组的指针。Malloc有足够的内存。初始化数组元素。然后使用fwrite将数组写入二进制文件。然后尝试读取相同的数据,返回到另一个指向类似数组的指针中,该数组有足够的内存 #include<stdio.h> typedef struct ss{ int *p; char c; double d; char g; float f; } dd; main(){ dd (*tt)[5]; int i=0,a[5]={4,1,6,9,3

我不明白节目中有什么错误。我正在定义一个指向结构数组的指针。Malloc有足够的内存。初始化数组元素。然后使用fwrite将数组写入二进制文件。然后尝试读取相同的数据,返回到另一个指向类似数组的指针中,该数组有足够的内存

#include<stdio.h>

typedef struct ss{
int *p;
char c;
double d;
char g;
float f;
} dd;

main(){

dd (*tt)[5];
int i=0,a[5]={4,1,6,9,3};
tt=malloc(sizeof(struct ss[5]));
for(i=0;i<5;i++){
   tt[i]->p=malloc(sizeof(int));
   tt[i]->p=&a[i];
   tt[i]->c=(char)('a'+i);
   tt[i]->d=(double)(5.234234+i);
   tt[i]->g=(char)('A'+i);
   tt[i]->f=(float)(15.234234+i);
}

FILE *F;
F=fopen("myfile","w+b");
size_t l;
l=fwrite(tt,sizeof(*tt),1,F);
fseek(F,0,SEEK_SET);
//printf("sizeof(dd)=%d   sizeof(*tt) =%d bytes written %d\n",sizeof(dd),sizeof(*tt),l);

dd (*xx)[5];

xx=malloc(sizeof(struct ss[5]));
l=fread(xx,sizeof(*xx),1,F);

for(i=0;i<5;i++){
printf("%d, %c,%f,%c,%f\n",*(xx[i]->p),xx[i]->c,xx[i]->d,xx[i]->g,xx[i]->f);
}
printf("Date Read %d \n",l);
for(i=0;i<5;i++){
free(xx[i]->p);
}
free(xx);
free(tt);
fclose(F);
remove("myfile");
}
#包括
类型定义结构ss{
int*p;
字符c;
双d;
charg;
浮动f;
}dd;
main(){
dd(*tt)[5];
int i=0,a[5]={4,1,6,9,3};
tt=malloc(sizeof(struct ss[5]);
对于(i=0;ip=malloc(sizeof(int));
tt[i]>p=&a[i];
tt[i]>c=(char)('a'+i);
tt[i]>d=(双)(5.234234+i);
tt[i]>g=(char)('A'+i);
tt[i]>f=(浮动)(15.234234+i);
}
文件*F;
F=fopen(“我的文件”,“w+b”);
大小;
l=fwrite(tt,sizeof(*tt),1,F);
fseek(F,0,SEEK_集);
//printf(“sizeof(dd)=%d sizeof(*tt)=%d字节写入%d\n”,sizeof(dd),sizeof(*tt),l);
dd(*xx)[5];
xx=malloc(sizeof(struct ss[5]);
l=fread(xx,sizeof(*xx),1,F);
对于(i=0;ip),xx[i]>c,xx[i]>d,xx[i]>g,xx[i]>f);
}
printf(“日期读取%d\n”,l);
对于(i=0;ip);
}
免费(xx);
免费(tt);
fclose(F);
删除(“myfile”);
}
输出:
4,a,5.234234,a,15.234234

分段错误

您的指针使用不正确。在此代码段中:

dd (*xx)[5];

xx=malloc(sizeof(struct ss[5]));
l=fread(xx,sizeof(*xx),1,F);

for(i=0;i<5;i++){
printf("%d, %c,%f,%c,%f\n",*(xx[i]->p),xx[i]->c,xx[i]->d,xx[i]->g,xx[i]->f);
}
当从0迭代到5时,每次数组访问都会将内存中的数组sizeof(ss[5])字节而不是sizeof(ss)字节提前。取出多余的指针

dd* xx;
xx = (dd*)malloc(sizeof(dd) * 5);
l = fread(xx, sizeof(dd), 5, F);

for(i = 0; i < 5; ++i) {
  printf("%d, %c, %f, %c, %f\n", xx[i].p, , xx[i].c, xx[i].d, xx[i].g, xx[i].f);
}

您没有在您认为的地方编写数据,因为您访问的
tt
不正确。您的错误访问是一致的,因此您可以读取第一条记录,但第二条记录与您想象的相差甚远—事实上,它正在写入未初始化的内存中,并且从未保存过。尝试访问重新加载的数据会显示这一点。此外,结构中的int*无法按编写方式正确写入,但这是没有意义的,因为程序是如何构造的-如果试图在程序的单独运行中加载文件,则会出错
fwrite
fread
无法跟随您的
int*
,因为它只是将您的结构视为一个位模式-它忠实地重建了您的指针,但现在您有了一个指向随机内存块的指针,而您实际上并没有使用它!不过,在这种情况下,指针仍然有效,因为您从未重写数据,但这是特定于这样的场景:将文件写出来,不刷新内存,然后在不关闭程序的情况下将其读回,这对于文件写入来说是不现实的

无论如何,在删除其他行的情况下,如何访问内存存在更大的问题:

dd (*tt)[5];
//...
tt=malloc(sizeof(struct ss[5]));
for(i=0;i<5;i++){
   tt[i]->p=malloc(sizeof(int));
   tt[i]->p=&a[i];
   //...
}
tt
是指向struct
dd
数组的指针,但您刚才将其视为指向struct
dd
的指针数组

你想要的是:

  • 取消引用
    tt
  • 在指向
    dd
  • 转到字段
    p
  • 为它指定一个指向整数空格的指针
你真正得到的是:

  • 在指向
    dd
  • 取消对它的引用,将其视为指向
    dd
    的指针,因为C不知道数组和指针之间的区别
  • 间接转到字段
    p
  • 为它指定一个指向整数空格的指针
i
为0时,这会正常工作,因为数组中的第0个元素和数组本身位于同一位置。(数组没有头,C_不理解数组和指针之间的区别,并允许您互换使用它们,这就是为什么它可以编译。)

i
不是0时,内存会变得非常混乱。现在,您正在写入跟随指针发生的任何内存!它实际上是一个指针,但你告诉C它是一个数组,它相信你,在它的位置上增加了1个元素宽度,并尝试执行所有这些操作。在应该使用指针的地方使用数组,在应该使用数组的地方使用指针

只能写入为元素0分配的内存。除此之外,您正在写入无关的内存,正是运气(在您的情况下是运气不好)阻止了您的程序在那里崩溃。(如果有,你会更容易找到这条线。)当你
fwrite
你分配的内存时,第一个元素是有效的,其余的是垃圾,你的
fread
会产生一个有一个有效元素的数据结构,然后是随机堆垃圾,当您尝试取消引用指针时导致崩溃(这只会因为程序没有结束而有效)

以下是访问数组指针的正确方法:

(*tt[i].p=malloc(sizeof(int))

另外,您正在分配内存,然后立即忘记了对它的唯一引用,这是内存泄漏,因为您正在用对初始化所有内容的静态数组的引用覆盖指针。改用这个:

*((*tt[i].p)=a[i]

我强烈鼓励你全面学习。它将帮助您在将来避免此类问题


请注意,以完全相同的方式打印其内容时,您读取的
xx
不正确。

我知道,编写指向文件的指针是个坏主意。我做这个练习只是为了更好地理解指向数组的指针。你说得很清楚,谢谢。我将读取该数组的和指针链接+1在mem泄漏捕捉器上。我现在更改了指针只保留静态数组地址的代码。
Writing application:
    int *p = 0x12345 ---> 5
0x12345 gets stored in the file for p.

Writing application reads the file.
    int *p = 0x12345 ---> 5
The pointer still points at the same memory because it is still the same memory
  layout.

New application reads the file.
    int *p = 0x12345 ---> ?????
The pointer doesn't point to a known piece of memory because the memory layout
  has changed in this new instance of the application. This could crash or
  cause a security issue.
dd (*tt)[5];
//...
tt=malloc(sizeof(struct ss[5]));
for(i=0;i<5;i++){
   tt[i]->p=malloc(sizeof(int));
   tt[i]->p=&a[i];
   //...
}
tt[i]->p=malloc(sizeof(int));