前言:
这是一个初学者不经意间就会犯的错误,这也困扰了本人几天,如果这篇文章对你有帮助,希望能获得你的一颗小点赞,这便是我继续下去的最大动力。本文纯属对所经历的错误做的一个小小的记录,若有其他指导意见或自己的见解,可以评论区与我畅谈。本题是释放了不是malloc的空间导致错误。
错题目录
结构体初始化
//结构体1 typedef struct { int* arr; int capacity; }ST; void StackInit(ST* ps) //结构体初始化 { assert(ps); ps->arr = malloc(4*sizeof(int)); //malloc数组存放数据 ps->capacity = 0; //记录容量 } //结构体2 typedef struct { ST push; //结构体2包含两个结构体变量 ST pop; } MyQueue; MyQueue* myQueueCreate() { MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue)); //结构体2也是malloc出来的 StackInit(&queue->push); StackInit(&queue->pop); return queue; }
两个结构体的之间的关系如图:
结构体释放
//结构体1释放 void StackDestroy(ST* ps) { free(ps->arr); ps->capacity = 0; ps->top = 0; ps->arr = NULL; free(ps) } //结构体2释放 void myQueueFree(MyQueue* obj) { StackDestroy(&obj->push); StackDestroy(&obj->pop); //利用stack销毁,实现queue销毁 free(obj); //这里在统一释放queue的内容 obj= NULL; }
呈现的错误
=================================================================
==42==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x603000000020 in thread T0
#0 0x7f1bebad87cf in __interceptor_free (/lib/x86_64-linux-gnu/libasan.so.5+0x10d7cf)
#4 0x7f1beae930b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
0x603000000020 is located 16 bytes inside of 32-byte region [0x603000000010,0x603000000030)
allocated by thread T0 here:
#0 0x7f1bebad8bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#4 0x7f1beae930b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: bad-free (/lib/x86_64-linux-gnu/libasan.so.5+0x10d7cf) in __interceptor_free
==42==ABORTING
原因
void StackDestroy(ST* ps)
{
free(ps->arr);
ps->capacity = 0;
ps->top = 0;
ps->arr = NULL;
//free(ps) //这里错误!!!
}
解释:释放了不属于malloc的空间 attempting free on address which was not malloc()-ed,由于queue结构体是一次malloc创建的,怎么申请就要怎么释放,不能分多次释放,上图free(ps)是释放了push这个结构体,但是由关系图可知push和queue是指向同一个位置的,而且queue又是一次性malloc建立的,故free(ps)也就是free(&push)就连同pop所在的一整块queue一起释放了。再次访问StackDestroy(&obj->pop) 时pop已经不存在。无法再次释放。
反思回顾
注意malloc要怎么创建怎么释放,注意每个函数调用的任务,StackDestroy是释放结构体1里面的数组arr的存储空间,再由myQueueFree释放queue的空间也就是释放push和pop的空间。
StackDestroy(&obj->pop);
StackDestroy(&obj->push);
同样的若保留free(ps),这两个函数交换释放也是不行的,释放一次malloc不能分两次释放,先释放pop,那么释放push的时候又会再次释放一次pop的空间。也是同样的错误。
所以pop和push是queue动态分配的,也要由释放queue统一释放。最重要的是怎么创建怎么释放,函数的任务要分清楚。