今早写链表的代码时,出现了未加载 wntdll.pdb这样一个问题。此贴将总结出现这类问题的原因和解决方法。(不断更新)
先上图:
出现这个异常,基本和堆区的重复内存释放没跑。
情况一:深拷贝与浅拷贝
如果一个类的成员变量,是开放在堆区的,
那么我们必须要重载拷贝构造函数。
因为默认的拷贝构造函数是浅拷贝,只是单纯的赋值。
举个例子来讲解:
class Person
{
public:
int* age;
Person(int age)
{
this->age = new int(age);
}
//Person(Person& p)
//{
// this->age = new int(*(p.age));
//}
~Person()
{
if (this->age != NULL)
free(this->age);
this->age = NULL;
}
};
int main()
{
Person p1(5);
Person p2(p1);
return 0;
}
我们创建了一个人类,其姓名是一个整型指针。
这里如果不进行深拷贝,那么会这样:
第一个人p1,他的成员变量age指向堆区的某个地址x。
这时候我们创建了一个人p2,用浅拷贝拷贝了p1。
那么他也有一个成员变量age,指向同一个地址x。
进行析构函数时,
p1和p2会进行对这个地址的两次释放,也就是内存重复释放,
所以出现了这个错误。
改进方法是,重载拷贝函数,在堆区重新开辟一块同样大小的新空间,然后让本对象的本成员函数指向那块新空间即可。
Person(Person& p)
{
this->age = new int(*(p.age));
}
情况二:反转链表 操纵的是同一个链表
因为指针指向的是地址,操控的是地址,
所以如果几个指针指向同一块地址的话,
其中一个指针改变其指向,会影响全局。(和单纯的数据不一样)
比如看如下代码:
LinkedList Reverse(LinkedList& L)
{
Node* pre;
Node* cur;
Node* nex;
Node* head;
head = (Node*)malloc(sizeof(Node));
pre = NULL;
cur = L->next;
nex = NULL;
while (cur != NULL)
{
nex = cur->next;
cur->next = pre;
pre = cur;
cur = nex;
}
head->next = pre;
free(cur);
cur = NULL;
free(nex);
nex = NULL;
return head;
}
cout << "请输入单链表的数据:";
LinkedList list, start;
list = LinkedListCreatT();
//LinkedListDelete(list, 3);
for (start = list->next; start != NULL; start = start->next)
{
cout << start->data << " ";
}
cout << endl;
LinkedList list2 = Reverse(list);
for (start = list->next; start != NULL; start = start->next)
{
cout << start->data << " ";
}
cout << endl;
LinkedListFree(list);
LinkedListFree(list2);
if (list == NULL)
{
cout << "链表已释放完毕" << endl;
}
这里的Reverse(list)其实就是list,而list2也是list,
结果我们重复使用了两次free函数来释放list,
自然会造成堆区内存重复释放。