鱼C论坛

 找回密码
 立即注册
查看: 884|回复: 6

[已解决]结构体套指针问题

[复制链接]
发表于 2022-2-23 00:47:21 | 显示全部楼层 |阅读模式

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

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

x

调试在 freeSpace里面报错,j =2 时运行在 if(ts[i]->students[j]!=NULL)  报错。
感谢感谢感谢

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. typedef struct Teacher
  5. {
  6.         char *name;
  7.         char **students;
  8. }STS;
  9. void test1(STS ***ts)
  10. {
  11.         STS **teacher = malloc(sizeof(STS *)*3);
  12.        
  13.                 for(int i=0;i<3;i++)
  14.                 {
  15.                         // 给每一个老师开辟空间
  16.                         teacher[i] = malloc(sizeof(STS));
  17.                         // 给老师姓名开辟空间
  18.                         teacher[i]->name = malloc(32);
  19.                         // 给老师姓名赋值
  20.                         sprintf(teacher[i]->name,"teacher%d",i+1);
  21.                         //给老师带的学生开辟空间
  22.                         teacher[i]->students = malloc(sizeof(char *)*5);
  23.                        
  24.                         for(int j=0;j<5;j++)
  25.                         {
  26.                                 //给老师 i 带的每个同学的姓名开辟空间
  27.                                 teacher[i]->students[j] = malloc(32);
  28.                                 // 给每个学生姓名赋值
  29.                                 sprintf(teacher[i]->students[j],"%dstudent%d",i+1,j+1);
  30.                         }
  31.                 }
  32.                 *ts = teacher;
  33.        
  34. }
  35. void printfInformation(STS **teacher)
  36. {
  37.         for(int i=0;i<3;i++)
  38.         {
  39.                 printf("%s:\n",teacher[i]->name);
  40.                
  41.                 for(int j=0;j<5;j++)
  42.                 {
  43.                         printf("\t%s\n",teacher[i]->students[j]);
  44.                 }
  45.         }
  46.         return ;
  47. }
  48. void freeSpace(STS **ts)   //-----------------------------------------------这里
  49. {
  50.         if(ts==NULL)
  51.         {
  52.                 return ;
  53.         }
  54.         for(int i=0;i<3;i++)
  55.         {
  56.                 //释放老师的名字
  57.                 if(ts[i]->name!=0)
  58.                 {
  59.                         free(ts[i]->name);
  60.                         ts[i]->name =NULL;
  61.                 }
  62.                 printf("teacher[%d]->name\n",i);
  63.                 for(int j=0;j<5;j++)
  64.                 {
  65.                         // 释放学生的姓名
  66.                         if(ts[i]->students[j]!=NULL)  //--------------------------------第二次运行在这里报错
  67.                         {
  68.                                 free(ts[i]->students[j]);
  69.                                 ts[i]->students[j] =NULL;
  70.                                 printf("\tteacher[%d]->students[%d]\n",i,j);
  71.                          }
  72.                         //释放学生
  73.                         if(ts[i]->students!=0)
  74.                         {
  75.                                 free(ts[i]->students);
  76.                                 ts[i]->students = NULL;
  77.                                 printf("\tteacher[%d]->students\n",i);
  78.                          }
  79.                 }
  80.                 //释放每一个老师
  81.                 if(ts[i]!=0)
  82.                 {
  83.                         free(ts[i]);
  84.                         ts[i] =NULL;
  85.                 }
  86.                
  87.         }
  88.         free(ts);
  89.         ts =NULL;
  90. }
  91. int main()
  92. {
  93.         STS ** ts =NULL;
  94.         test1(&ts); // 开辟空间 ,并赋值
  95.         printfInformation(ts); // 打印信息
  96.         freeSpace(ts); // err
  97.         ts =NULL;
  98.        
  99.        
  100.         return 0;
  101. }
复制代码
最佳答案
2022-2-23 01:47:20
其实这个代码写的可以,就是你写代码的时候不是成对编写,这就导致嵌套的层数多了,就有可能出问题了
这里你把这个写到for循环里面了 free(ts[i]->students);
如果成对编写,或者说照着申请内存的函数写释放内存的函数
就没问题


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. typedef struct Teacher
  5. {
  6.         char *name;
  7.         char **students;
  8. }STS;
  9. void test1(STS ***ts)
  10. {
  11.         STS **teacher = malloc(sizeof(STS *)*3);
  12.         
  13.                 for(int i=0;i<3;i++)
  14.                 {
  15.                         // 给每一个老师开辟空间
  16.                         teacher[i] = malloc(sizeof(STS));
  17.                         // 给老师姓名开辟空间
  18.                         teacher[i]->name = malloc(32);
  19.                         // 给老师姓名赋值
  20.                         sprintf(teacher[i]->name,"teacher%d",i+1);
  21.                         //给老师带的学生开辟空间
  22.                         teacher[i]->students = malloc(sizeof(char *)*5);
  23.                         
  24.                         for(int j=0;j<5;j++)
  25.                         {
  26.                                 //给老师 i 带的每个同学的姓名开辟空间
  27.                                 teacher[i]->students[j] = malloc(32);
  28.                                 // 给每个学生姓名赋值
  29.                                 sprintf(teacher[i]->students[j],"%dstudent%d",i+1,j+1);
  30.                         }
  31.                 }
  32.                 *ts = teacher;
  33.         
  34. }
  35. void printfInformation(STS **teacher)
  36. {
  37.         for(int i=0;i<3;i++)
  38.         {
  39.                 printf("%s:\n",teacher[i]->name);
  40.                
  41.                 for(int j=0;j<5;j++)
  42.                 {
  43.                         printf("\t%s\n",teacher[i]->students[j]);
  44.                 }
  45.         }
  46.         return ;
  47. }
  48. void freeSpace(STS **ts)   //-----------------------------------------------这里
  49. {
  50.         if(ts==NULL)
  51.         {
  52.                 return ;
  53.         }
  54.         for(int i=0;i<3;i++)
  55.         {
  56.                 //释放老师的名字
  57.                 if(ts[i]->name!=0)
  58.                 {
  59.                         free(ts[i]->name);
  60.                         ts[i]->name =NULL;
  61.                 }
  62.                 printf("teacher[%d]->name\n",i);
  63.                 for(int j=0;j<5;j++)
  64.                 {
  65.                         // 释放学生的姓名
  66.                         if(ts[i]->students[j]!=NULL)  //--------------------------------第二次运行在这里报错
  67.                         {
  68.                                 free(ts[i]->students[j]);
  69.                                 ts[i]->students[j] =NULL;
  70.                                 printf("\tteacher[%d]->students[%d]\n",i,j);
  71.                          }
  72. // 就这里的问题
  73. #if 0
  74.                         //释放学生
  75.                         if(ts[i]->students!=0)
  76.                         {
  77.                                 free(ts[i]->students);
  78.                                 ts[i]->students = NULL;
  79.                                 printf("\tteacher[%d]->students\n",i);
  80.                          }
  81. #endif
  82.                 }


  83.                 //释放学生
  84.                 if(ts[i]->students!=0)
  85.                 {
  86.                         free(ts[i]->students);
  87.                         ts[i]->students = NULL;
  88.                         printf("\tteacher[%d]->students\n",i);
  89.                  }






  90.                 //释放每一个老师
  91.                 if(ts[i]!=0)
  92.                 {
  93.                         free(ts[i]);
  94.                         ts[i] =NULL;
  95.                 }
  96.                
  97.         }
  98.         free(ts);
  99.         ts =NULL;
  100. }
  101. int main()
  102. {
  103.         STS ** ts =NULL;
  104.         test1(&ts); // 开辟空间 ,并赋值
  105.         printfInformation(ts); // 打印信息
  106.         freeSpace(ts); // err
  107.         ts =NULL;
  108.         
  109.         
  110.         return 0;
  111. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-2-23 01:35:19 | 显示全部楼层
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. typedef struct Teacher {
  5.     char *name;
  6.     char **students;
  7. } STS;

  8. void test1(STS ***ts) {
  9.     STS **teacher = malloc(sizeof(STS *) * 3);
  10.     for(int i = 0; i < 3; i++) {
  11.         // 给每一个老师开辟空间
  12.         teacher[i] = malloc(sizeof(STS));
  13.         // 给老师姓名开辟空间
  14.         teacher[i]->name = malloc(32);
  15.         // 给老师姓名赋值
  16.         sprintf(teacher[i]->name, "teacher%d", i + 1);
  17.         // 给老师带的学生开辟空间
  18.         teacher[i]->students = malloc(sizeof(char *) * 5);

  19.         for(int j = 0; j < 5; j++) {
  20.             // 给老师 i 带的每个同学的姓名开辟空间
  21.             teacher[i]->students[j] = malloc(32);
  22.             // 给每个学生姓名赋值
  23.             sprintf(teacher[i]->students[j], "%dstudent%d", i + 1, j + 1);
  24.         }
  25.     }
  26.     *ts = teacher;
  27. }

  28. // 仔细看free的顺序是不是发现了一个规律?
  29. // free的顺序正好和malloc的顺序相反
  30. // 这样就一定不会出问题
  31. void free_space(STS **ts) {
  32.     if(!ts) return;
  33.     for(size_t i = 0; i < 3; ++i) {
  34.         for(size_t j = 0; j < 5; ++j) {
  35.             free(ts[i]->students[j]);
  36.         }
  37.         free(ts[i]->students);
  38.         free(ts[i]->name);
  39.         free(ts[i]);
  40.     }
  41.     free(ts);
  42. }

  43. void freeSpace(STS **ts) {
  44.     if(ts == NULL) return;
  45.     for(int i = 0; i < 3; i++) {
  46.         // 释放老师的名字
  47.         free(ts[i]->name);

  48.         free(NULL);     // 不会出问题,^_^

  49.         /*
  50.         //if(ts[i]->name != 0) {
  51.         if(ts[i]->name != NULL) {       // 写成这样更好
  52.                                         // 其实可以不判断的
  53.                                         // free(NULL);
  54.                                         // 这么写没有任何问题
  55.             free(ts[i]->name);
  56.             //ts[i]->name = NULL;       // 没有必要
  57.         }
  58.         */
  59.         printf("teacher[%d]->name\n", i);

  60.         for(int j = 0; j < 5; j++) {
  61.             free(ts[i]->students[j]);
  62.         }
  63.         free(ts[i]->students);
  64.         // 下面的代码有问题
  65.         /*
  66.         for(int j = 0; j < 5; j++) {
  67.             // 释放学生的姓名
  68.             if(ts[i]->students[j] != NULL) {
  69.                 free(ts[i]->students[j]);
  70.                 ts[i]->students[j] = NULL;
  71.                 printf("\tteacher[%d]->students[%d]\n", i, j);
  72.             }
  73.             // 释放学生
  74.             if(ts[i]->students != 0) {
  75.                 free(ts[i]->students);
  76.                 ts[i]->students = NULL;
  77.                 printf("\tteacher[%d]->students\n", i);
  78.             }
  79.         }
  80.         */
  81.         // 释放每一个老师
  82.         if(ts[i] != 0) {
  83.             free(ts[i]);
  84.             ts[i] = NULL;
  85.         }
  86.     }
  87.     free(ts);
  88.     //ts = NULL;           // 写这个同样多余,而且这里的这条语句还容易让人误解
  89.                            // 反正我刚看到这里的时候就认为这里有问题,应该是 *ts = NULL;
  90.                            // 但是通过进一步看代码,发现这里没有问题,写 *ts = NULL; 反而有问题
  91. }

  92. void printfInformation(STS **teacher) {
  93.     for(int i = 0; i < 3; i++) {
  94.         printf("%s:\n", teacher[i]->name);

  95.         for(int j = 0; j < 5; j++) {
  96.             printf("\t%s\n", teacher[i]->students[j]);
  97.         }
  98.     }
  99.     return;
  100. }

  101. int main() {
  102.     STS **ts = NULL;
  103.     test1(&ts);            // 开辟空间 ,并赋值
  104.     printfInformation(ts); // 打印信息
  105.     freeSpace(ts);         // err
  106.     //free_space(ts);

  107.     //ts = NULL;           // 我感觉没有必要,当然写上也不会有问题
  108.                            // 这个可写可不写,我是不写的
  109.                            // 我能保证这里不出问题
  110.                            // 至少到目前为止,我还没有在这个位置出现过问题
  111.                            // 我不写这个,我有这自信,^_^
  112.     return 0;
  113. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-23 01:47:20 | 显示全部楼层    本楼为最佳答案   
其实这个代码写的可以,就是你写代码的时候不是成对编写,这就导致嵌套的层数多了,就有可能出问题了
这里你把这个写到for循环里面了 free(ts[i]->students);
如果成对编写,或者说照着申请内存的函数写释放内存的函数
就没问题


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. typedef struct Teacher
  5. {
  6.         char *name;
  7.         char **students;
  8. }STS;
  9. void test1(STS ***ts)
  10. {
  11.         STS **teacher = malloc(sizeof(STS *)*3);
  12.         
  13.                 for(int i=0;i<3;i++)
  14.                 {
  15.                         // 给每一个老师开辟空间
  16.                         teacher[i] = malloc(sizeof(STS));
  17.                         // 给老师姓名开辟空间
  18.                         teacher[i]->name = malloc(32);
  19.                         // 给老师姓名赋值
  20.                         sprintf(teacher[i]->name,"teacher%d",i+1);
  21.                         //给老师带的学生开辟空间
  22.                         teacher[i]->students = malloc(sizeof(char *)*5);
  23.                         
  24.                         for(int j=0;j<5;j++)
  25.                         {
  26.                                 //给老师 i 带的每个同学的姓名开辟空间
  27.                                 teacher[i]->students[j] = malloc(32);
  28.                                 // 给每个学生姓名赋值
  29.                                 sprintf(teacher[i]->students[j],"%dstudent%d",i+1,j+1);
  30.                         }
  31.                 }
  32.                 *ts = teacher;
  33.         
  34. }
  35. void printfInformation(STS **teacher)
  36. {
  37.         for(int i=0;i<3;i++)
  38.         {
  39.                 printf("%s:\n",teacher[i]->name);
  40.                
  41.                 for(int j=0;j<5;j++)
  42.                 {
  43.                         printf("\t%s\n",teacher[i]->students[j]);
  44.                 }
  45.         }
  46.         return ;
  47. }
  48. void freeSpace(STS **ts)   //-----------------------------------------------这里
  49. {
  50.         if(ts==NULL)
  51.         {
  52.                 return ;
  53.         }
  54.         for(int i=0;i<3;i++)
  55.         {
  56.                 //释放老师的名字
  57.                 if(ts[i]->name!=0)
  58.                 {
  59.                         free(ts[i]->name);
  60.                         ts[i]->name =NULL;
  61.                 }
  62.                 printf("teacher[%d]->name\n",i);
  63.                 for(int j=0;j<5;j++)
  64.                 {
  65.                         // 释放学生的姓名
  66.                         if(ts[i]->students[j]!=NULL)  //--------------------------------第二次运行在这里报错
  67.                         {
  68.                                 free(ts[i]->students[j]);
  69.                                 ts[i]->students[j] =NULL;
  70.                                 printf("\tteacher[%d]->students[%d]\n",i,j);
  71.                          }
  72. // 就这里的问题
  73. #if 0
  74.                         //释放学生
  75.                         if(ts[i]->students!=0)
  76.                         {
  77.                                 free(ts[i]->students);
  78.                                 ts[i]->students = NULL;
  79.                                 printf("\tteacher[%d]->students\n",i);
  80.                          }
  81. #endif
  82.                 }


  83.                 //释放学生
  84.                 if(ts[i]->students!=0)
  85.                 {
  86.                         free(ts[i]->students);
  87.                         ts[i]->students = NULL;
  88.                         printf("\tteacher[%d]->students\n",i);
  89.                  }






  90.                 //释放每一个老师
  91.                 if(ts[i]!=0)
  92.                 {
  93.                         free(ts[i]);
  94.                         ts[i] =NULL;
  95.                 }
  96.                
  97.         }
  98.         free(ts);
  99.         ts =NULL;
  100. }
  101. int main()
  102. {
  103.         STS ** ts =NULL;
  104.         test1(&ts); // 开辟空间 ,并赋值
  105.         printfInformation(ts); // 打印信息
  106.         freeSpace(ts); // err
  107.         ts =NULL;
  108.         
  109.         
  110.         return 0;
  111. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-23 01:52:38 | 显示全部楼层
我要吐槽一下你写的这注释
// 给每一个老师开辟空间
// 释放每一个老师

// 给每一个teacher开辟空间
// 释放每一个teacher
我感觉有些单词还是不翻译的好,翻译成中文以后感觉怪怪的,^_^
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-23 01:58:04 | 显示全部楼层
可以看出,这里我把 freeSpace 和 printfInformation 的顺序换了一下
就是为了写 freeSpace 函数的时候(或者说检查 freeSpace 函数的时候),方便对照申请内存的函数(这里的 test1)
内存怎么申请的就怎么释放,释放的顺序和申请的顺序相反,这样就不会有问题
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-23 08:47:26 | 显示全部楼层
人造人 发表于 2022-2-23 01:52
我要吐槽一下你写的这注释
// 给每一个老师开辟空间
// 释放每一个老师

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

使用道具 举报

 楼主| 发表于 2022-2-23 08:54:19 | 显示全部楼层
人造人 发表于 2022-2-23 01:47
其实这个代码写的可以,就是你写代码的时候不是成对编写,这就导致嵌套的层数多了,就有可能出问题了
这里 ...

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

使用道具 举报

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

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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