鱼C论坛

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

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

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

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

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

x

调试在 freeSpace里面报错,j =2 时运行在 if(ts[i]->students[j]!=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[i] = malloc(sizeof(STS));
                        // 给老师姓名开辟空间 
                        teacher[i]->name = malloc(32);
                        // 给老师姓名赋值 
                        sprintf(teacher[i]->name,"teacher%d",i+1);
                        //给老师带的学生开辟空间
                        teacher[i]->students = malloc(sizeof(char *)*5);
                        
                        for(int j=0;j<5;j++)
                        {
                                //给老师 i 带的每个同学的姓名开辟空间 
                                teacher[i]->students[j] = malloc(32);
                                // 给每个学生姓名赋值 
                                sprintf(teacher[i]->students[j],"%dstudent%d",i+1,j+1); 
                        } 
                }
                *ts = teacher;
        
}
void printfInformation(STS **teacher) 
{
        for(int i=0;i<3;i++)
        {
                printf("%s:\n",teacher[i]->name);
                
                for(int j=0;j<5;j++)
                {
                        printf("\t%s\n",teacher[i]->students[j]);
                }
        }
        return ;
}
void freeSpace(STS **ts)   //-----------------------------------------------这里
{
        if(ts==NULL)
        {
                return ;
        }
        for(int i=0;i<3;i++)
        {
                //释放老师的名字 
                if(ts[i]->name!=0)
                {
                        free(ts[i]->name);
                        ts[i]->name =NULL;
                }
                printf("teacher[%d]->name\n",i); 
                for(int j=0;j<5;j++)
                {
                        // 释放学生的姓名 
                        if(ts[i]->students[j]!=NULL)  //--------------------------------第二次运行在这里报错
                        {
                                free(ts[i]->students[j]);
                                ts[i]->students[j] =NULL;
                                printf("\tteacher[%d]->students[%d]\n",i,j);
                         } 
                        //释放学生 
                        if(ts[i]->students!=0)
                        {
                                free(ts[i]->students);
                                ts[i]->students = NULL;
                                printf("\tteacher[%d]->students\n",i);
                         } 
                }
                //释放每一个老师 
                if(ts[i]!=0)
                {
                        free(ts[i]);
                        ts[i] =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:47:20
其实这个代码写的可以,就是你写代码的时候不是成对编写,这就导致嵌套的层数多了,就有可能出问题了
这里你把这个写到for循环里面了 free(ts[i]->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[i] = malloc(sizeof(STS));
                        // 给老师姓名开辟空间 
                        teacher[i]->name = malloc(32);
                        // 给老师姓名赋值 
                        sprintf(teacher[i]->name,"teacher%d",i+1);
                        //给老师带的学生开辟空间
                        teacher[i]->students = malloc(sizeof(char *)*5);
                        
                        for(int j=0;j<5;j++)
                        {
                                //给老师 i 带的每个同学的姓名开辟空间 
                                teacher[i]->students[j] = malloc(32);
                                // 给每个学生姓名赋值 
                                sprintf(teacher[i]->students[j],"%dstudent%d",i+1,j+1); 
                        } 
                }
                *ts = teacher;
        
}
void printfInformation(STS **teacher) 
{
        for(int i=0;i<3;i++)
        {
                printf("%s:\n",teacher[i]->name);
                
                for(int j=0;j<5;j++)
                {
                        printf("\t%s\n",teacher[i]->students[j]);
                }
        }
        return ;
}
void freeSpace(STS **ts)   //-----------------------------------------------这里
{
        if(ts==NULL)
        {
                return ;
        }
        for(int i=0;i<3;i++)
        {
                //释放老师的名字 
                if(ts[i]->name!=0)
                {
                        free(ts[i]->name);
                        ts[i]->name =NULL;
                }
                printf("teacher[%d]->name\n",i); 
                for(int j=0;j<5;j++)
                {
                        // 释放学生的姓名 
                        if(ts[i]->students[j]!=NULL)  //--------------------------------第二次运行在这里报错
                        {
                                free(ts[i]->students[j]);
                                ts[i]->students[j] =NULL;
                                printf("\tteacher[%d]->students[%d]\n",i,j);
                         } 
// 就这里的问题
#if 0
                        //释放学生 
                        if(ts[i]->students!=0)
                        {
                                free(ts[i]->students);
                                ts[i]->students = NULL;
                                printf("\tteacher[%d]->students\n",i);
                         } 
#endif
                }


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






                //释放每一个老师 
                if(ts[i]!=0)
                {
                        free(ts[i]);
                        ts[i] =NULL;
                }
                
        }
        free(ts);
        ts =NULL;
} 
int main()
{
        STS ** ts =NULL;
        test1(&ts); // 开辟空间 ,并赋值 
        printfInformation(ts); // 打印信息
        freeSpace(ts); // err
        ts =NULL;
        
        
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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[i] = malloc(sizeof(STS));
        // 给老师姓名开辟空间
        teacher[i]->name = malloc(32);
        // 给老师姓名赋值
        sprintf(teacher[i]->name, "teacher%d", i + 1);
        // 给老师带的学生开辟空间
        teacher[i]->students = malloc(sizeof(char *) * 5);

        for(int j = 0; j < 5; j++) {
            // 给老师 i 带的每个同学的姓名开辟空间
            teacher[i]->students[j] = malloc(32);
            // 给每个学生姓名赋值
            sprintf(teacher[i]->students[j], "%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[i]->students[j]);
        }
        free(ts[i]->students);
        free(ts[i]->name);
        free(ts[i]);
    }
    free(ts);
}

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

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

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

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

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

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

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

    //ts = NULL;           // 我感觉没有必要,当然写上也不会有问题
                           // 这个可写可不写,我是不写的
                           // 我能保证这里不出问题
                           // 至少到目前为止,我还没有在这个位置出现过问题
                           // 我不写这个,我有这自信,^_^
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-23 01:47:20 | 显示全部楼层    本楼为最佳答案   
其实这个代码写的可以,就是你写代码的时候不是成对编写,这就导致嵌套的层数多了,就有可能出问题了
这里你把这个写到for循环里面了 free(ts[i]->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[i] = malloc(sizeof(STS));
                        // 给老师姓名开辟空间 
                        teacher[i]->name = malloc(32);
                        // 给老师姓名赋值 
                        sprintf(teacher[i]->name,"teacher%d",i+1);
                        //给老师带的学生开辟空间
                        teacher[i]->students = malloc(sizeof(char *)*5);
                        
                        for(int j=0;j<5;j++)
                        {
                                //给老师 i 带的每个同学的姓名开辟空间 
                                teacher[i]->students[j] = malloc(32);
                                // 给每个学生姓名赋值 
                                sprintf(teacher[i]->students[j],"%dstudent%d",i+1,j+1); 
                        } 
                }
                *ts = teacher;
        
}
void printfInformation(STS **teacher) 
{
        for(int i=0;i<3;i++)
        {
                printf("%s:\n",teacher[i]->name);
                
                for(int j=0;j<5;j++)
                {
                        printf("\t%s\n",teacher[i]->students[j]);
                }
        }
        return ;
}
void freeSpace(STS **ts)   //-----------------------------------------------这里
{
        if(ts==NULL)
        {
                return ;
        }
        for(int i=0;i<3;i++)
        {
                //释放老师的名字 
                if(ts[i]->name!=0)
                {
                        free(ts[i]->name);
                        ts[i]->name =NULL;
                }
                printf("teacher[%d]->name\n",i); 
                for(int j=0;j<5;j++)
                {
                        // 释放学生的姓名 
                        if(ts[i]->students[j]!=NULL)  //--------------------------------第二次运行在这里报错
                        {
                                free(ts[i]->students[j]);
                                ts[i]->students[j] =NULL;
                                printf("\tteacher[%d]->students[%d]\n",i,j);
                         } 
// 就这里的问题
#if 0
                        //释放学生 
                        if(ts[i]->students!=0)
                        {
                                free(ts[i]->students);
                                ts[i]->students = NULL;
                                printf("\tteacher[%d]->students\n",i);
                         } 
#endif
                }


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






                //释放每一个老师 
                if(ts[i]!=0)
                {
                        free(ts[i]);
                        ts[i] =NULL;
                }
                
        }
        free(ts);
        ts =NULL;
} 
int main()
{
        STS ** ts =NULL;
        test1(&ts); // 开辟空间 ,并赋值 
        printfInformation(ts); // 打印信息
        freeSpace(ts); // err
        ts =NULL;
        
        
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

// 给每一个teacher开辟空间
// 释放每一个teacher
我感觉有些单词还是不翻译的好,翻译成中文以后感觉怪怪的,^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

使用道具 举报

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

好好
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

十分感谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-7-10 19:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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