想入门的新人 发表于 2022-2-23 00:47:21

结构体套指针问题


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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Teacher
{
        char *name;
        char **students;
}STS;
void test1(STS ***ts)
{
        STS **teacher = malloc(sizeof(STS *)*3);
       
                for(int i=0;i<3;i++)
                {
                        // 给每一个老师开辟空间
                        teacher = malloc(sizeof(STS));
                        // 给老师姓名开辟空间
                        teacher->name = malloc(32);
                        // 给老师姓名赋值
                        sprintf(teacher->name,"teacher%d",i+1);
                        //给老师带的学生开辟空间
                        teacher->students = malloc(sizeof(char *)*5);
                       
                        for(int j=0;j<5;j++)
                        {
                                //给老师 i 带的每个同学的姓名开辟空间
                                teacher->students = malloc(32);
                                // 给每个学生姓名赋值
                                sprintf(teacher->students,"%dstudent%d",i+1,j+1);
                        }
                }
                *ts = teacher;
       
}
void printfInformation(STS **teacher)
{
        for(int i=0;i<3;i++)
        {
                printf("%s:\n",teacher->name);
               
                for(int j=0;j<5;j++)
                {
                        printf("\t%s\n",teacher->students);
                }
        }
        return ;
}
void freeSpace(STS **ts)   //-----------------------------------------------这里
{
        if(ts==NULL)
        {
                return ;
        }
        for(int i=0;i<3;i++)
        {
                //释放老师的名字
                if(ts->name!=0)
                {
                        free(ts->name);
                        ts->name =NULL;
                }
                printf("teacher[%d]->name\n",i);
                for(int j=0;j<5;j++)
                {
                        // 释放学生的姓名
                        if(ts->students!=NULL)//--------------------------------第二次运行在这里报错
                        {
                                free(ts->students);
                                ts->students =NULL;
                                printf("\tteacher[%d]->students[%d]\n",i,j);
                       }
                        //释放学生
                        if(ts->students!=0)
                        {
                                free(ts->students);
                                ts->students = NULL;
                                printf("\tteacher[%d]->students\n",i);
                       }
                }
                //释放每一个老师
                if(ts!=0)
                {
                        free(ts);
                        ts =NULL;
                }
               
        }
        free(ts);
        ts =NULL;
}
int main()
{
        STS ** ts =NULL;
        test1(&ts); // 开辟空间 ,并赋值
        printfInformation(ts); // 打印信息
        freeSpace(ts); // err
        ts =NULL;
       
       
        return 0;
}

人造人 发表于 2022-2-23 01:35:19

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Teacher {
    char *name;
    char **students;
} STS;

void test1(STS ***ts) {
    STS **teacher = malloc(sizeof(STS *) * 3);
    for(int i = 0; i < 3; i++) {
      // 给每一个老师开辟空间
      teacher = malloc(sizeof(STS));
      // 给老师姓名开辟空间
      teacher->name = malloc(32);
      // 给老师姓名赋值
      sprintf(teacher->name, "teacher%d", i + 1);
      // 给老师带的学生开辟空间
      teacher->students = malloc(sizeof(char *) * 5);

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

// 仔细看free的顺序是不是发现了一个规律?
// free的顺序正好和malloc的顺序相反
// 这样就一定不会出问题
void free_space(STS **ts) {
    if(!ts) return;
    for(size_t i = 0; i < 3; ++i) {
      for(size_t j = 0; j < 5; ++j) {
            free(ts->students);
      }
      free(ts->students);
      free(ts->name);
      free(ts);
    }
    free(ts);
}

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

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

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

      for(int j = 0; j < 5; j++) {
            free(ts->students);
      }
      free(ts->students);
      // 下面的代码有问题
      /*
      for(int j = 0; j < 5; j++) {
            // 释放学生的姓名
            if(ts->students != NULL) {
                free(ts->students);
                ts->students = NULL;
                printf("\tteacher[%d]->students[%d]\n", i, j);
            }
            // 释放学生
            if(ts->students != 0) {
                free(ts->students);
                ts->students = NULL;
                printf("\tteacher[%d]->students\n", i);
            }
      }
      */
      // 释放每一个老师
      if(ts != 0) {
            free(ts);
            ts = NULL;
      }
    }
    free(ts);
    //ts = NULL;         // 写这个同样多余,而且这里的这条语句还容易让人误解
                           // 反正我刚看到这里的时候就认为这里有问题,应该是 *ts = NULL;
                           // 但是通过进一步看代码,发现这里没有问题,写 *ts = NULL; 反而有问题
}

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

      for(int j = 0; j < 5; j++) {
            printf("\t%s\n", teacher->students);
      }
    }
    return;
}

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

    //ts = NULL;         // 我感觉没有必要,当然写上也不会有问题
                           // 这个可写可不写,我是不写的
                           // 我能保证这里不出问题
                           // 至少到目前为止,我还没有在这个位置出现过问题
                           // 我不写这个,我有这自信,^_^
    return 0;
}

人造人 发表于 2022-2-23 01:47:20

其实这个代码写的可以,就是你写代码的时候不是成对编写,这就导致嵌套的层数多了,就有可能出问题了
这里你把这个写到for循环里面了 free(ts->students);
如果成对编写,或者说照着申请内存的函数写释放内存的函数
就没问题


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Teacher
{
      char *name;
      char **students;
}STS;
void test1(STS ***ts)
{
      STS **teacher = malloc(sizeof(STS *)*3);
      
                for(int i=0;i<3;i++)
                {
                        // 给每一个老师开辟空间
                        teacher = malloc(sizeof(STS));
                        // 给老师姓名开辟空间
                        teacher->name = malloc(32);
                        // 给老师姓名赋值
                        sprintf(teacher->name,"teacher%d",i+1);
                        //给老师带的学生开辟空间
                        teacher->students = malloc(sizeof(char *)*5);
                        
                        for(int j=0;j<5;j++)
                        {
                              //给老师 i 带的每个同学的姓名开辟空间
                              teacher->students = malloc(32);
                              // 给每个学生姓名赋值
                              sprintf(teacher->students,"%dstudent%d",i+1,j+1);
                        }
                }
                *ts = teacher;
      
}
void printfInformation(STS **teacher)
{
      for(int i=0;i<3;i++)
      {
                printf("%s:\n",teacher->name);
               
                for(int j=0;j<5;j++)
                {
                        printf("\t%s\n",teacher->students);
                }
      }
      return ;
}
void freeSpace(STS **ts)   //-----------------------------------------------这里
{
      if(ts==NULL)
      {
                return ;
      }
      for(int i=0;i<3;i++)
      {
                //释放老师的名字
                if(ts->name!=0)
                {
                        free(ts->name);
                        ts->name =NULL;
                }
                printf("teacher[%d]->name\n",i);
                for(int j=0;j<5;j++)
                {
                        // 释放学生的姓名
                        if(ts->students!=NULL)//--------------------------------第二次运行在这里报错
                        {
                              free(ts->students);
                              ts->students =NULL;
                              printf("\tteacher[%d]->students[%d]\n",i,j);
                         }
// 就这里的问题
#if 0
                        //释放学生
                        if(ts->students!=0)
                        {
                              free(ts->students);
                              ts->students = NULL;
                              printf("\tteacher[%d]->students\n",i);
                         }
#endif
                }


                //释放学生
                if(ts->students!=0)
                {
                        free(ts->students);
                        ts->students = NULL;
                        printf("\tteacher[%d]->students\n",i);
               }






                //释放每一个老师
                if(ts!=0)
                {
                        free(ts);
                        ts =NULL;
                }
               
      }
      free(ts);
      ts =NULL;
}
int main()
{
      STS ** ts =NULL;
      test1(&ts); // 开辟空间 ,并赋值
      printfInformation(ts); // 打印信息
      freeSpace(ts); // err
      ts =NULL;
      
      
      return 0;
}

人造人 发表于 2022-2-23 01:52:38

我要吐槽一下你写的这注释
// 给每一个老师开辟空间
// 释放每一个老师

// 给每一个teacher开辟空间
// 释放每一个teacher
我感觉有些单词还是不翻译的好,翻译成中文以后感觉怪怪的,^_^

人造人 发表于 2022-2-23 01:58:04

可以看出,这里我把 freeSpace 和 printfInformation 的顺序换了一下
就是为了写 freeSpace 函数的时候(或者说检查 freeSpace 函数的时候),方便对照申请内存的函数(这里的 test1)
内存怎么申请的就怎么释放,释放的顺序和申请的顺序相反,这样就不会有问题

想入门的新人 发表于 2022-2-23 08:47:26

人造人 发表于 2022-2-23 01:52
我要吐槽一下你写的这注释
// 给每一个老师开辟空间
// 释放每一个老师


{:10_257:}好好

想入门的新人 发表于 2022-2-23 08:54:19

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

十分感谢{:10_281:}
页: [1]
查看完整版本: 结构体套指针问题