【C++】关于指针Free和链表循环释放的问题
关于指针Free和链表循环的问题
- 由于在做某项目的主架构师,有大半年时间没有手敲过代码了。虽然一直有在review代码(各种语言的…),但是业务居多。
- 最近经历某个诡异的Bug,在链表循环时会莫名崩溃。最后查下来,都是基础的知识点(一下子没想起来…)。这里记录一下(不涉及任何项目内容,只涉及基础技术)
指针Free
其实就是释放指针对象。考虑下面的伪代码
void freeMe(void* p)
{
assert(p != NULL)
delete p;
p = NULL;
}
int main()
{
int* testMe = new int(1);
freeMe(testMe);
if (testMe == NULL) {
// testMe是否为NULL???
}
}
- 上述代码中,testMe是否能释放?testMe判空是否生效?
- testMe可以释放,但是testMe判空不生效。形参只是指向了一份相同的地址,让形参指向空,不会让testMe指向NULL。
该问题可以通过下述方式解决
void freeMe(void* p)
{
assert(p != NULL)
delete p;
p = NULL;
}
void freeMeReal(void** p)
{
assert(p != NULL);
freeMe(*ptr)
*p = NULL;
}
int main()
{
int* testMe = new int(1);
freeMe(&testMe);
if (testMe == NULL) {
// testMe为空。
}
}
链表循环释放
- 链表在循环释放时,如果操作不当,可以会访问一块非法地址。导致崩溃现象。考虑如下代码
struct Node
{
struct Node *next;
void* data;
} Node_t;
struct List {
Node *head;
Node *tail;
} List_t;
void fff() {
List MyList;
for (Node t = MyList.head; t != NULL, t = t->next) {
if (等于某个条件下删除) {
Node * next = t->next;
// 让前一个节点,指向被删除节点的next
prev->next = next;
free(t);
// 这俩就会产生问题,t已经被释放了,但是下次仍使用t->next
}
}
}
- 上述代码的问题在于,当前节点已被删除的情况下。使用了被free掉的地址,进行Next操作。这样会导致概率性崩溃
- 修改方式。
void fff() {
List MyList;
for (Node t = MyList.head; t != NULL, t = t->next) {
if (等于某个条件下删除) {
Node * next = t->next;
// 让前一个节点,指向被删除节点的next
prev->next = next ;
free(t);
// 将t指向上一个节点。
t = prev;
}
}
}