为什么这种情况下动态申请内存要预先固定申请字节大小?用sizeof的话,释放空间时程序会崩溃

striveQiao 2018-11-04 04:19:33
在用结构体嵌套二级指针时,动态分配空间。
结构体定义如图


申请空间如下:

上面两个圈出的地方为什么都必须固定大小?不能用sizeof来自由分配吗?

这样任意改一处程序就会崩溃

释放代码块


就像问问到底什么时候用sizeof申请内存,什么时候不可以用sizeof申请内存?

全部代码
#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

//重写结构体嵌套一级指针老师和二级指针学生
//结构体类型每个老师有3个学生
typedef struct Teacher {
char *tName;//导师
char **stu;//3个学生
int age;
}Teacher;
//定义全局变量
int i = 0;
int j = 0;

//在createTeacher中分配空间
int createTeacher(Teacher **p/*out*/, int n1, int n2)
{
int i = 0;
int j = 0;
if (p == NULL)
{
return -1;
}

Teacher *temp = (Teacher*)malloc(sizeof(Teacher)*n1);
for (i = 0; i < n1; i++)
{
//导师
temp[i].tName = (char *)malloc(100);
char **s = (char**)malloc(sizeof(char*)*n1);//定义临时变量
for (j = 0; j < n2; j++)
{
//学生
s[j] = (char*)malloc(100);
}
temp[i].stu = s;

}
//间接赋值
*p = temp;

return 0;
}
//给成员赋值

void initTeacher(Teacher *p, int n1, int n2)
{

if (p == NULL)
{
return;
}
char buf[100];
for (i = 0; i < n1; i++)
{

sprintf(buf, "teacher%d%d", i, i);
strcpy(p[i].tName, buf);
for (j = 0; j < n2; j++)
{

sprintf(buf, "stu%d%d", i, j);
strcpy(p[i].stu[j], buf);

}
p[i].age = 20 + i;
printf("\n");
}

}



//打印结构体成员

void printTeacher(Teacher *p, int n1, int n2)
{
if (p == NULL)
{
return;
}
for (i = 0; i < n1; i++)
{
printf("%s: ",p[i].tName);
printf("age:%d ", p[i].age);
for (j = 0; j < n2; j++)
{
printf("%s\t", p[i].stu[j]);
}
}
printf("\n");
}

//根据导师名字排序,降序
void sortTeacher(Teacher *p, int n1, int n2)
{
char *temp;
for (i = 0; i < n1 - 1; i++)
{
for (j = i + 1; j < n2; j++)
{
if (strcmp(p[i].tName, p[j].tName) < 0)
{
temp = p[i].tName;
p[i].tName = p[j].tName;
p[j].tName = temp;
}
}
}
}
//释放空间,在函数内部把p赋值为NULL,所以需要二级指针
void freeTeacher(Teacher **p, int n1, int n2)
{
if (p == NULL)
{
return;
}
Teacher *temp = *p;//定义临时变量,把首地址接过来
for (i = 0; i < n1; i++)
{
//释放老师
if (temp[i].tName != NULL)
{
free(temp[i].tName);
temp[i].tName = NULL;
}
for (j = 0; j < n2; j++)
{
if (temp[i].stu[j] != NULL)
{
free(temp[i].stu[j]);
temp[i].stu[j] = NULL;
}
}
if (temp[i].stu != NULL)
{
free(temp[i].stu);
temp[i].stu = NULL;
}
}
if (temp != NULL)
{
free(temp);
*p = NULL;
}

}

int main()
{
Teacher *p = NULL;
int n1=3;//导师个数
int n2=3;//学生个数
int ret = 0;
ret=createTeacher(&p, n1, n2);
createTeacher(&p, n1, n2);
initTeacher(p, n1, n2);
printf("排序前:\n");
printTeacher(p, n1, n2);
sortTeacher(p, n1, n2);
printf("排序后:\n");
printTeacher(p, n1, n2);
freeTeacher(&p, n1, n2);

system("pause");
return 0;
}
...全文
123 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
jdgdf566 2018-11-06
  • 打赏
  • 举报
回复
引用 8 楼 bravery36 的回复:
[quote=引用 7 楼 jdgdf566 的回复:]
对于结构体,最好是用偏移量的差值代替sizeof,偏移量差值是指,结构体创建之后(不是定义之后),尾首两个指针相减。

这是什么鬼说法? 结构体任何时候都可以用sizeof, 只有指针不能用sizeof, sizeof(structtype)的大小肯定是对的.[/quote]
你是理论而已,编译器有实际情况
bravery36 2018-11-06
  • 打赏
  • 举报
回复
引用 7 楼 jdgdf566 的回复:
对于结构体,最好是用偏移量的差值代替sizeof,偏移量差值是指,结构体创建之后(不是定义之后),尾首两个指针相减。

这是什么鬼说法? 结构体任何时候都可以用sizeof, 只有指针不能用sizeof, sizeof(structtype)的大小肯定是对的.
jdgdf566 2018-11-06
  • 打赏
  • 举报
回复
对于结构体,最好是用偏移量的差值代替sizeof,偏移量差值是指,结构体创建之后(不是定义之后),尾首两个指针相减。
自信男孩 2018-11-05
  • 打赏
  • 举报
回复
#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

//重写结构体嵌套一级指针老师和二级指针学生
//结构体类型每个老师有3个学生
//
#define MAX_NAME_SIZE 64
typedef struct Teacher {
char *tName;//导师
char **stu;//3个学生
int age;
}Teacher;
//定义全局变量

//int i = 0;
//int j = 0;

//在createTeacher中分配空间
int createTeacher(Teacher **p/*out*/, int n1, int n2)
{
//int i = 0;
//int j = 0;
int i, j;
if (p == NULL)
{
return -1;
}

Teacher *temp = (Teacher*)malloc(sizeof(Teacher)*n1);
for (i = 0; i < n1; i++)
{
//导师
temp[i].tName = (char *)malloc(sizeof(char) * MAX_NAME_SIZE);
char **s = (char **)malloc(sizeof(char*)*n1);//定义临时变量
for (j = 0; j < n2; j++)
{
//学生
s[j] = (char*)malloc(sizeof(char) * MAX_NAME_SIZE);
}
temp[i].stu = s;

}
//间接赋值
*p = temp;

return 0;
}
//给成员赋值

void initTeacher(Teacher *p, int n1, int n2)
{

char buf[MAX_NAME_SIZE];
int i, j;

if (p == NULL)
{
return;
}
for (i = 0; i < n1; i++)
{
sprintf(buf, "teacher%d%d", i, i);
strcpy(p[i].tName, buf);
for (j = 0; j < n2; j++)
{

sprintf(buf, "stu%d%d", i, j);
strcpy(p[i].stu[j], buf);

}
p[i].age = 20 + i;
printf("\n");
}

}



//打印结构体成员

void printTeacher(Teacher *p, int n1, int n2)
{
int i, j;
if (p == NULL)
{
return;
}
for (i = 0; i < n1; i++)
{
printf("%s: ",p[i].tName);
printf("age:%d ", p[i].age);
for (j = 0; j < n2; j++)
{
printf("%s\t", p[i].stu[j]);
}
}
printf("\n");
}

//根据导师名字排序,降序
void sortTeacher(Teacher *p, int n1, int n2)
{
Teacher temp;
int i, j;
for (i = 0; i < n1 - 1; i++)
{
for (j = i + 1; j < n2; j++)
{
if (strcmp(p[i].tName, p[j].tName) < 0)
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
}
//释放空间,在函数内部把p赋值为NULL,所以需要二级指针
void freeTeacher(Teacher **p, int n1, int n2)
{
int i, j;

if (p == NULL)
{
return;
}
Teacher *temp = *p;//定义临时变量,把首地址接过来
for (i = 0; i < n1; i++)
{
//释放老师
if (temp[i].tName != NULL)
{
free(temp[i].tName);
temp[i].tName = NULL;
}
for (j = 0; j < n2; j++)
{
if (temp[i].stu[j] != NULL)
{
free(temp[i].stu[j]);
temp[i].stu[j] = NULL;
}
}
if (temp[i].stu != NULL)
{
free(temp[i].stu);
temp[i].stu = NULL;
}
}
if (temp != NULL)
{
free(temp);
*p = NULL;
}

}

int main()
{
Teacher *p = NULL;
int n1=3;//导师个数
int n2=3;//学生个数
int ret = 0;
ret=createTeacher(&p, n1, n2);
createTeacher(&p, n1, n2);
initTeacher(p, n1, n2);
printf("排序前:\n");
printTeacher(p, n1, n2);
sortTeacher(p, n1, n2);
printf("排序后:\n");
printTeacher(p, n1, n2);
freeTeacher(&p, n1, n2);

system("pause");
return 0;
}


供参考,
你的问题应该是内存越界导致的。而不是释放导致的
英雄@末路 2018-11-05
  • 打赏
  • 举报
回复
createTeacher函数里面 char **s 后面那一段代码的逻辑重新捋一下吧,感觉你有什么误解在里面。
636f6c696e 2018-11-05
  • 打赏
  • 举报
回复
tName只是个指针,sizeof无法得到正确的大小 你说的这个问题可以用宏定义来解决 #define NAME_LEN 100 malloc(NAME_LEN)
幻夢之葉 2018-11-04
  • 打赏
  • 举报
回复
因为栈被破坏导致的崩溃, 是你分配了内存太小导致越界赋值了


在你这个改动下:s[j] = (char*)malloc(sizeof(char)*n2)) //n2 == 3
才3字节大小

sprintf(buf, "teacher%d%d", i, i); //至少10字节
strcpy(p[i].tName, buf);
sprintf(buf, "stu%d%d", i, j); //至少6字节
strcpy(p[i].stu[j], buf);

还有就是,完整的写法自然是
(char*)malloc(sizeof(char)*100))
又因为char被固定为1字节,所以sizeof(char) == 1,省略即为(char*)malloc(100)
www_adintr_com 2018-11-04
  • 打赏
  • 举报
回复

char **s = (char**)malloc(sizeof(char*)*n1);//定义临时变量
        for (j = 0; j < n2; j++)
        {
            //学生
            s[j] = (char*)malloc(100);
        }
申请的个数是 n1, 访问的时候是 n2, 这不是赤裸裸的越界么....
lkj2016 2018-11-04
  • 打赏
  • 举报
回复
Teacher *p = NULL;
ret=createTeacher(&p, n1, n2);
p=null没有地址

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧