如何正确释放双指针指向的结构体内存?及代码错误排查
如何正确释放双指针指向的结构体内存?
咱们来看看你遇到的这个问题,先把你的代码和编译报错贴出来:
原错误代码
// 释放与handle参数指向的Item相关的所有动态分配内存 // 并将Item指针设置为NULL void deleteItem(Item** item) { free(item->name); free(item); *item = NULL; }
编译错误信息
make gcc -c item.c -g -Wall
item.c: In function ‘deleteItem’:
item.c:48:12: error: request for member ‘name’ in something not a structure or union
free(&item->name);
^
Makefile:1...
为啥会报错?
你这里踩了个二级指针的常见坑:item是二级指针(Item**类型),它指向的是一个Item*指针,而不是直接指向结构体实例。所以直接写item->name的时候,编译器会困惑:你这是要访问一个指针的name成员?但指针本身不是结构体/联合体啊!这就是报错的核心原因。另外,free(item)也是错的——item是函数的参数(存在栈上),你要释放的是它指向的那个Item实例,也就是*item,而不是参数本身。
正确的实现方式
你需要先对二级指针item做一次解引用,拿到它指向的Item*(一级指针),然后再访问结构体的name成员。同时加上空指针检查,避免崩溃。修正后的代码如下:
void deleteItem(Item** item) { // 先做防御性检查:如果传入的二级指针是空,或者它指向的一级指针是空,直接返回 if (item == NULL || *item == NULL) { return; } // 先释放结构体内部的动态分配内存(name字符串) free((*item)->name); // 再释放结构体实例本身的内存 free(*item); // 把原指针置为NULL,避免调用方后续访问野指针 *item = NULL; }
关键步骤拆解
- 空指针检查:这是防御性编程的好习惯,避免传入空指针时解引用导致程序崩溃。
(*item)->name:先通过*item拿到指向结构体的一级指针,再用->访问name成员,释放这个动态分配的字符串内存。free(*item):释放结构体实例本身的内存,因为*item才是指向这个实例的指针。*item = NULL:把调用方传入的那个一级指针置为NULL,这样调用方就不会再访问已经被释放的内存(彻底杜绝野指针问题)。
内容的提问来源于stack exchange,提问作者Broque
相关产品推荐
相关产品推荐

