鱼C论坛

 找回密码
 立即注册
查看: 1296|回复: 16

[已解决]结构体类型变量问题,求助,感谢感谢

[复制链接]
发表于 2022-2-7 13:56:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

代码运行至printf("%s %d %d",ss.name,ss.id,ss.name_len);这里就报错。

Program received signal SIGSEGV, Segmentation fault。


  1. #include<stdio.h>
  2. #include<string.h>
  3. #include <stdlib.h>
  4. //        将以下结构体类型变量,以二进制的形式存放到文件中,并且可以实现读的接口,打印读出来信息。

  5. typedef struct Student
  6. {
  7.         char *name;                //名字
  8.         int id;
  9.         int name_len;        //名字长度
  10. }Stu;

  11. int main()
  12. {

  13.         Stu s;        //定义结构体变量
  14.         //结构体成员赋值
  15.         s.id = 1;
  16.         s.name_len = strlen("mike"); //名字长度
  17.         s.name = (char *)malloc(s.name_len + 1);
  18.         strcpy(s.name, "mike");
  19.        
  20.         FILE *ff=fopen("信息.txt","a+");
  21.         if(!ff) return -1;
  22.                 printf("%s %d %d",s.name,s.id,s.name_len);
  23.         int num=fwrite(&s,1,sizeof(Stu),ff);       
  24.         printf("共存入%d个字节!",num);
  25.        
  26.         fclose(ff);
  27.         ff=fopen("信息.txt","r");
  28.         if(!ff) return -1;
  29.         Stu ss;
  30.         ss.name=(char *)malloc(64);
  31.         int nuu=fread(&ss,1,sizeof(Stu),ff);
  32.         printf("共%d个字节!",nuu);
  33.         printf("%s %d %d",ss.name,ss.id,ss.name_len);
  34.        
  35.        
  36.         free(s.name);
  37.         free(ss.name);
  38.         return 0;
  39. }
复制代码



感谢帮助
感谢帮助
谢谢
最佳答案
2022-2-12 10:47:39
想入门的新人 发表于 2022-2-12 09:16
编译过得了,调试就出现
Program received signal SIGSEGV, Segmentation fault
就是第36行或者40行这 ...
  1. free(s.name);
  2. free(ss.name);//因为fread函数读取文件ss.name和s.name指针一样,你上面为ss.name申请内存得到的指针值已经被改变,这样重复释放内存当然报错,还有只把字符串指针写入文件有什么用
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-2-7 14:15:15 | 显示全部楼层
改成
  1. #include<stdio.h>
  2. #include<string.h>
  3. #include <stdlib.h>
  4. //        将以下结构体类型变量,以二进制的形式存放到文件中,并且可以实现读的接口,打印读出来信息。

  5. typedef struct Student
  6. {
  7.         char *name;                //名字
  8.         int id;
  9.         int name_len;        //名字长度
  10. }Stu;

  11. int main()
  12. {

  13.         Stu s;        //定义结构体变量
  14.         //结构体成员赋值
  15.         s.id = 1;
  16.         s.name_len = strlen("mike"); //名字长度
  17.         s.name = (char *)malloc(s.name_len + 1);
  18.         strcpy(s.name, "mike");
  19.       
  20.         FILE *ff=fopen("信息.txt","ab+");  // 我改了这里
  21.         if(!ff) return -1;
  22.                 printf("%s %d %d",s.name,s.id,s.name_len);
  23.         int num=fwrite(&s,1,sizeof(Stu),ff);      
  24.         printf("共存入%d个字节!",num);
  25.       
  26.         fclose(ff);
  27.         ff=fopen("信息.txt","rb");  // 我改了这里
  28.         if(!ff) return -1;
  29.         Stu ss;
  30.         ss.name=(char *)malloc(64);
  31.         int nuu=fread(&ss,1,sizeof(Stu),ff);
  32.         printf("共%d个字节!",nuu);
  33.         printf("%s %d %d",ss.name,ss.id,ss.name_len);
  34.       
  35.       
  36.         free(s.name);
  37.         free(ss.name);
  38.         return 0;
  39. }
复制代码

试试
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-8 16:25:59 | 显示全部楼层

小学五年级会挺多的,挺厉害的,谢谢了
这里还是不行
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-10 17:39:27 | 显示全部楼层
请问具体报的是什么错呀?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-12 09:16:34 | 显示全部楼层
番杰 发表于 2022-2-10 17:39
请问具体报的是什么错呀?

编译过得了,调试就出现
Program received signal SIGSEGV, Segmentation fault
就是第36行或者40行这里编译不过去。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-12 10:47:39 | 显示全部楼层    本楼为最佳答案   
想入门的新人 发表于 2022-2-12 09:16
编译过得了,调试就出现
Program received signal SIGSEGV, Segmentation fault
就是第36行或者40行这 ...
  1. free(s.name);
  2. free(ss.name);//因为fread函数读取文件ss.name和s.name指针一样,你上面为ss.name申请内存得到的指针值已经被改变,这样重复释放内存当然报错,还有只把字符串指针写入文件有什么用
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-12 17:28:41 | 显示全部楼层

【还有只把字符串指针写入文件有什么用】
这里讲的是哪呀?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-12 17:31:29 | 显示全部楼层

感谢感谢,我把后面改成这样就可以了

  1. //        ss.name=NULL;
  2. //        ss.name=(char *)malloc(64);
  3.         if(ss.name==NULL) return 1;
  4.         int nuu=fread(&ss,1,sizeof(Stu),ff);
  5.         printf("共%d个字节!",nuu);

  6.         printf("%s %d %d",ss.name,ss.id,ss.name_len);
  7.        
  8.         free(s.name);
  9. //        free(ss.name);
复制代码
改成这样就可以了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-12 19:38:37 | 显示全部楼层
想入门的新人 发表于 2022-2-12 17:28
【还有只把字符串指针写入文件有什么用】
这里讲的是哪呀?


i
  1. int num=fwrite(&s,1,sizeof(Stu),ff);//只把结构体里的char *name字符串指针变量写入文件,没有把字符串写入文件,应该在后面把name指向的字符串写入文件  
  2. num=fwrite(s.name,1,s.name_len + 1,ff);//读取时别忘了读完一个结构体在读入一个字符串
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2022-2-19 10:55:57 | 显示全部楼层
  1. #include<stdio.h>
  2. #include<string.h>
  3. #include <stdlib.h>
  4. //        将以下结构体类型变量,以二进制的形式存放到文件中,并且可以实现读的接口,打印读出来信息。

  5. typedef struct Student
  6. {
  7.         char *name;                //名字
  8.         int id;
  9.         int name_len;        //名字长度
  10. }Stu;

  11. int main()
  12. {

  13.         Stu s;        //定义结构体变量
  14.         //结构体成员赋值
  15.         s.id = 1;
  16.         s.name_len = strlen("mike"); //名字长度
  17.         s.name = (char *)malloc(s.name_len + 1);
  18.         strcpy(s.name, "mike");
  19.        
  20.         FILE *ff=fopen("信息.txt","w");
  21.         if(!ff)
  22.         {
  23.                 perror("2");
  24.                 return -1;
  25.         }
  26.                 printf("%s %d %d",s.name,s.id,s.name_len);
  27.         int num=fwrite(&s,1,sizeof(Stu),ff);//只把结构体里的char *name字符串指针变量写入文件,没有把字符串写入文件,应该在后面把name指向的字符串写入文件  
  28.                 printf("共存入%d个字节!",num);
  29.          num=fwrite(s.name,1,s.name_len + 1,ff);//读取时别忘了读完一个结构体在读入一个字符串       
  30.         printf("共存入%d个字节!",num);
  31.        
  32.         fclose(ff);
  33.         ff=fopen("信息.txt","r");
  34.         if(!ff)
  35.         {
  36.                 perror("1");
  37.                 return -1;
  38.         }
  39.         Stu ss;
  40.         free(s.name);
  41.         ss.name=NULL;
  42.         ss.name=(char *)malloc(64);
  43.         if(ss.name==NULL) return 1;
  44.         int nuu=fread(&ss,1,sizeof(Stu),ff);
  45.         printf("共%d个字节!",nuu);
  46.         nuu=fread(ss.name,1,ss.name_len+1,ff);
  47.         printf("共%d个字节!",nuu);

  48.         printf("%s %d %d",ss.name,ss.id,ss.name_len);
  49.        
  50.        
  51.        
  52.         free(ss.name);
  53.         return 0;
  54. }
复制代码

假如我改成这样先释放掉free(s.name),然后重新开辟ss.name ,这里运行调试至free(ss.name)还是会崩
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-19 11:40:06 | 显示全部楼层
本帖最后由 jhq999 于 2022-2-19 11:43 编辑
  1.         Stu ss;
  2.         free(s.name);
  3.         ss.name=NULL;
  4.         //ss.name=(char *)malloc(64);
  5.         //if(ss.name==NULL) return 1;
  6.         int nuu=fread(&ss,1,sizeof(Stu),ff);//如果在前面申请空间,经过fread函数后ss.name这个指针会被改变成文件储存的指针值
  7.         printf("共%d个字节!",nuu);
  8.         
  9.         ss.name=(char *)malloc(64);////////////////////////
  10.         if(ss.name==NULL) return 1;////////////////////////
  11.         
  12.         nuu=fread(ss.name,1,ss.name_len+1,ff);
  13.         printf("共%d个字节!",nuu);

  14.         printf("%s %d %d",ss.name,ss.id,ss.name_len);
  15.         
  16.         
  17.         
  18.         free(ss.name);
  19.         return 0;
  20. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-19 11:47:12 | 显示全部楼层

这里在前面开辟空间不行吗,还是说提前开辟后,fread会将之前s.name所指向的地址拷贝过来,如果是这样,那么我在开辟ss.name后在用一个 char *p=ss.name ,在最后的时候free(p)行吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-19 11:49:24 | 显示全部楼层
想入门的新人 发表于 2022-2-19 11:47
这里在前面开辟空间不行吗,还是说提前开辟后,fread会将之前s.name所指向的地址拷贝过来,如果是这样, ...
  1. Stu ss;
  2.         free(s.name);
  3.         ss.name=NULL;
  4.         ss.name=(char *)malloc(64);
  5.         char *p =ss.name; //-----------------------
  6.         if(ss.name==NULL) return 1;
  7.         int nuu=fread(&ss,1,sizeof(Stu),ff);
  8.         printf("共%d个字节!",nuu);
  9.         nuu=fread(ss.name,1,ss.name_len+1,ff);
  10.         printf("共%d个字节!",nuu);

  11.         printf("%s %d %d",ss.name,ss.id,ss.name_len);
  12.        
  13.        
  14.        
  15. //        free(ss.name); // 报错
  16.         free(p);//--------------------
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-19 11:52:20 | 显示全部楼层
本帖最后由 jhq999 于 2022-2-19 11:55 编辑
想入门的新人 发表于 2022-2-19 11:47
这里在前面开辟空间不行吗,还是说提前开辟后,fread会将之前s.name所指向的地址拷贝过来,如果是这样, ...


可以,但你后面的字符串读取到哪里,p?对于结构体有什么用,还得在读字符串之前让ss.name=p;多了好几行代码和一个变量
  1. Stu ss;
  2.         free(s.name);
  3.         ss.name=NULL;
  4.         ss.name=(char *)malloc(64);
  5.         char *p =ss.name; //-----------------------
  6.         if(ss.name==NULL) return 1;
  7.         int nuu=fread(&ss,1,sizeof(Stu),ff);
  8.         printf("共%d个字节!",nuu);
  9.         nuu=fread(p,1,ss.name_len+1,ff);/////////
  10.         ss.name=p;/////////////////////
  11.         printf("共%d个字节!",nuu);

  12.         printf("%s %d %d",ss.name,ss.id,ss.name_len);
  13.         
  14.         
  15.         
  16.          free(ss.name);
  17.     //   free(p);//--------------------
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-19 15:06:45 | 显示全部楼层
jhq999 发表于 2022-2-19 11:52
可以,但你后面的字符串读取到哪里,p?对于结构体有什么用,还得在读字符串之前让ss.name=p;多了好几行 ...

fwrite写进文件的时候是将 id的内容 ,name保存的地址 和len的内容拷贝进文件的吗?
那再一次fwrite(s.name,1,sizeof(s.len)+1,file)时会把之前保存的name地址覆盖吗?
感谢感谢感谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-19 15:18:04 | 显示全部楼层
想入门的新人 发表于 2022-2-19 15:06
fwrite写进文件的时候是将 id的内容 ,name保存的地址 和len的内容拷贝进文件的吗?
那再一次fwrite(s. ...

如果没重新打开文件,或者没有主动让位置指针移动,那么会写在后面,顺便问一下,读写文件你学了吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-19 15:41:03 | 显示全部楼层
jhq999 发表于 2022-2-19 15:18
如果没重新打开文件,或者没有主动让位置指针移动,那么会写在后面,顺便问一下,读写文件你学了吗?


                               
登录/注册后可看大图

我是这样想的,按我的思路的话,在fread(&ss,1,sizeof(Stu),fiile) ,后打印出ss.name应该是乱码,这里保存的是之前s.name molloc后的地址,fread(ss.name,1,5,file)后,将内容拷贝到之前被释放了的地址应该是非法操作
但是我打印出来却是内容mike,只有释放的时候显示报错


这里我学过文件的读写,我写入文件的结构体里面没遇见过有指针的,然后就有点不明白,感谢老哥费心思给我讲解,谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-25 02:58

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表