背景
在写
#173二叉搜索树迭代器
的时候,遇到了如下报错:
报错内容
=================================================================
==45==ERROR: AddressSanitizer: attempting double-free on 0x7fa0cd690800 in thread T0:
#0 0x7fa0cca11b8f in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10bb8f)
#4 0x7fa0cb9f682f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
0x7fa0cd690800 is located 0 bytes inside of 400008-byte region [0x7fa0cd690800,0x7fa0cd6f2288)
freed by thread T0 here:
#0 0x7fa0cca11b8f in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10bb8f)
#4 0x7fa0cb9f682f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
previously allocated by thread T0 here:
#0 0x7fa0cca11f88 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10bf88)
#5 0x7fa0cb9f682f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
SUMMARY: AddressSanitizer: double-free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10bb8f) in __interceptor_free
==45==ABORTING
翻译
管他三七二十一,先翻译一下报错信息:
ERROR: AddressSanitizer: attempting double-free
错误:尝试双重释放
实际操作
释放,free。这个关键词说明了我们的代码是在释放的时候出了问题。
于是我们去寻找有free()函数的地方:
void bSTIteratorFree(BSTIterator* obj) {
free(obj->val);
free(obj);
}
乍一看也没啥问题啊,先释放里面的数据结果(此处为一维数组val),然后再释放整个结构体变量。
但是转念一想,问题来了。如果
obj->val
本身就为空呢?这时候哪来的
obj->val
?释放个锤子?
解释一下,BSTIterator 是一个栈,obj->top为栈顶指针
于是在释放obj->val之前加上了判断,如下
void bSTIteratorFree(BSTIterator* obj) {
if(obj->val) free(obj->val);
free(obj);
}
然而这时候可以发现,也没法全A.
再仔细一想,如果结构体变量
obj
如果本身不存在,又何来的
obj->val
?
于是如下修改:
void bSTIteratorFree(BSTIterator* obj) {
if(obj && obj->val) free(obj->val);
free(obj);
}
这样子就解决了上面的报错问题,并完成了题目。想看看题目是啥?请点
传送门
后记
诸如此类语句:
BSTIterator* obj = (BSTIterator *)malloc(sizeof(BSTIterator));
if(!obj) return NULL;
obj->top = 0;
第二行的判断语句看似可有可无,但是,如果内存空间分配失败了呢?
这样一来obj就还只是一个空指针,又何来的
obj->top
?
异常判断,养成习惯
。
如果我们养成了好习惯,出现报错的概率岂不会下降很多?
自省,自省!
如果对你有帮助,请👍。(这是一波强烈的暗示)