C语言中双指针的释放时机及释放报错问题咨询
为什么释放双指针
pstr会报错?拆解指针与内存分配的核心区别 这个问题其实戳中了很多C语言初学者对指针和内存分配的误解点,我来给你一步步理清楚:
首先先确认你第一个场景的理解是完全正确的:
char **mat = (char**) malloc(sizeof(char*) * 100); for(int i = 0; i < 500; i++) mat[i] = (char*) malloc(sizeof(char) * 50);
这里的mat本身是通过malloc在堆内存上申请的一块空间(用来存100个char指针),而每个mat[i]又各自申请了堆内存来存字符串。所以释放时要先逐个释放mat[i](每个对应一次malloc),最后释放mat本身(对应最开始的那次malloc),完全符合“每个malloc对应一个free”的规则。
那为什么第二个场景会报错呢?我们来看这段代码:
char *str = (char *) malloc(100 * sizeof(char)); char **pstr = &str; free(pstr);
核心问题出在**pstr指向的地址不是malloc分配的堆内存**!
str是你在函数里声明的一个普通指针变量,它存在栈内存里,栈内存是程序自动管理的,不需要你手动释放,也绝对不能用free去碰。&str取到的是str这个栈变量的地址,把它赋值给pstr,此时pstr指向的是栈上的位置,而不是你用malloc申请的那100字节堆内存。- free的作用仅仅是释放从malloc/calloc/realloc返回的堆内存地址,你给它传一个栈地址,程序当然会报错“尝试释放无效指针”。
你真正需要释放的是str指向的堆内存,也就是free(str),而不是free(pstr)。
再举一个正确使用双指针并释放的例子
如果我们要让双指针本身也在堆上,应该这么写:
// 先在堆上申请一个能存char指针的空间 char **pstr = (char**)malloc(sizeof(char*)); // 让这个堆上的指针指向malloc出来的字符串 *pstr = (char*)malloc(100*sizeof(char)); // 释放顺序:先释放字符串,再释放双指针本身 free(*pstr); free(pstr);
这个场景里,pstr和*pstr都是堆内存,所以需要分别free,和你第一个数组的场景逻辑一致。
总结关键规则
- 只有malloc/calloc/realloc返回的堆内存地址才能用free释放,栈变量的地址绝对不能传进free。
- 对于双指针(
T**):- 如果
T**本身是malloc分配的(比如第一个例子的mat),需要先释放每个T*指向的堆内存,再释放T**本身。 - 如果
T**只是用来指向一个栈上的T*变量(比如你的第二个例子),这个T**不需要free,只需要free那个T*指向的堆内存即可。
- 如果
内容的提问来源于stack exchange,提问作者user9874031
相关产品推荐
相关产品推荐

