SmartPointer 列表中的错误 EXC_BAD_ACCESS
Error EXC_BAD_ACCESS in list with SmartPointer
当我从列表中删除一个元素时,我遇到了这个问题。
这是我的 list.h:
class AwesomeList {
friend class Iteratore;
private:
class Nodo;
class SmartPointer {
public:
Nodo* punt;
SmartPointer(Nodo* n = 0): punt(n) {}
SmartPointer(const SmartPointer& ptr): punt(ptr.punt) {}
~SmartPointer() {
delete punt;
}
SmartPointer& operator=(const SmartPointer& ptr) {
if (this != &ptr) {
delete punt;
punt = ptr.punt;
}
return *this;
}
bool operator==(const SmartPointer& ptr) const {
return ptr.punt == punt;
}
bool operator!=(const SmartPointer& ptr) const {
return ptr.punt != punt;
}
Nodo* operator->() const {
return punt;
}
Nodo& operator*() const {
return *punt;
}
};
class Nodo {
public:
T* value;
SmartPointer next;
Nodo(T* t = T(), const SmartPointer& ptr = SmartPointer()): value(t), next(ptr) {}
};
SmartPointer head;
SmartPointer tail;
public:
class Iteratore{
friend class AwesomeList;
private:
AwesomeList::SmartPointer punt;
public:
bool operator==(const Iteratore& it) const {
return it.punt == punt;
}
bool operator!=(const Iteratore& it) const {
return it.punt != punt;
}
Iteratore& operator++() {
if(punt != 0) punt = punt->next;
return *this;
}
Iteratore& operator++(int) {
if(punt != 0) punt = punt->next;
return *this;
}
T* operator*() const {
if (punt != 0) return punt->value;
}
};
AwesomeList(const SmartPointer& ptr = 0): head(ptr), tail(0) {
if (head != 0) {
SmartPointer p = head;
while (p != 0)
p = p->next;
tail = p;
}
}
AwesomeList(const AwesomeList& list): head(list.head), tail(list.tail) {}
AwesomeList& operator=(const AwesomeList& list) {
head = list.head;
tail = list.tail;
}
int getSize() const {
int count = 0;
SmartPointer p = head;
while (p != 0) {
p = p->next;
count++;
}
return count;
}
bool isEmpty() const {
return getSize() == 0;
}
T* at(int pos) const {
if (pos > -1 && pos < getSize()) {
SmartPointer p = head;
while (pos--) {
p = p->next;
}
return p->value;
} else return 0;
}
void add(const T& t) {
if (head == 0) {
head = SmartPointer(new Nodo(&(const_cast<T&>(t))));
tail = head;
} else {
tail->next = SmartPointer(new Nodo(&(const_cast<T&>(t))));
tail = tail->next;
}
}
void remove(int pos) {
if (pos > -1 && pos < getSize()) {
SmartPointer newHead = head;
SmartPointer p = newHead;
head = 0;
while (pos--) {
add(*p->value);
p = p->next;
}
p = p->next;
while (p != 0) {
add(*p->value);
p = p->next;
}
}
}
void replace(int pos, T* t) {
if (pos > -1 && pos < getSize()) {
SmartPointer p = head;
while (pos--)
p = p->next;
p->value = t;
}
}
void replace(int pos, const T& t) {
if (pos > -1 && pos < getSize()) {
SmartPointer p = head;
while (pos--)
p = p->next;
T& t_obj = const_cast<T&>(t);
p->value = &t_obj;
}
}
Iteratore begin() const {
Iteratore it;
it.punt = head;
return it;
}
Iteratore end() const {
Iteratore it;
it.punt = 0;
return it;
}
T* operator[](const Iteratore& it) const {
return it.punt->value;
}
};
这是我做的测试:
AwesomeList<int> list = AwesomeList<int>();
list.add(1);
list.add(2);
list.add(3);
for (int i = 0; i < list.getSize(); i++)
qDebug() <<*(list.at(i)) <<" ";
list.remove(-1);
for (int i = 0; i < list.getSize(); i++)
qDebug() <<*(list.at(i)) <<" ";
list.remove(2);
for (int i = 0; i < list.getSize(); i++)
qDebug() <<*(list.at(i)) <<" ";
list.replace(0, 5);
qDebug() <<"Replace in posizione 0";
auto cit = list.begin();
for (; cit != list.end(); cit++)
qDebug() <<*(*cit) <<" ";
qDebug() <<"Size";
qDebug() <<list.getSize() <<endl;
这是出现错误的行:
- AwesomeList::Nodo::~Nodo() + 16(真棒list.h:8)
- AwesomeList::SmartPointer::~SmartPointer() + 42(真棒list.h:21)
- AwesomeList::SmartPointer::~SmartPointer() + 21(真棒list.h:22)
感谢您的帮助。谢谢!
更新
我通过改变 SmartPointer 和 Nodo 类 解决了我的问题:
SmartPointer(Nodo* n = 0): punt(n) {
if (punt) punt->references++;
}
SmartPointer(const SmartPointer& ptr): punt(ptr.punt) {
if (punt) punt->references++;
}
~SmartPointer() {
if (punt) {
punt->references--;
if (punt->references == 0) delete punt;
}
}
SmartPointer& operator=(const SmartPointer& ptr) {
if (this != &ptr) {
Nodo* n = punt;
punt = ptr.punt;
if (punt) punt->references++;
if (n) {
n->references--;
if (n->references == 0) delete n;
}
}
return *this;
}
bool operator==(const SmartPointer& ptr) const {
return ptr.punt == punt;
}
bool operator!=(const SmartPointer& ptr) const {
return ptr.punt != punt;
}
Nodo* operator->() const {
return punt;
}
Nodo& operator*() const {
return *punt;
}
};
class Nodo {
public:
T* value;
SmartPointer next;
int references;
Nodo(T* t = T(), const SmartPointer& ptr = SmartPointer()): value(t), next(ptr), references(0) {}
};
抱歉,我不明白你下面的比例 SmartPointer
class。
它带有一个指向 Nodo
和 delete
构造函数的指针。好
但是,如果我没记错的话
(1) 当您使用复制构造函数创建 SmartPointer
时,您从复制的 SmartPointer
复制指针,因此您有两个具有相同值的 punt
的对象;当你销毁这两个对象时,你会在同一个指针上调用 delete
两次;这会使程序崩溃
(2)当你调用operator=
时,复制构造函数也有同样的问题,而且,你没有删除旧的指向值
举例看add()
head = SmartPointer(new Nodo(&(const_cast<T&>(t))));
tail = head;
您创建了一个临时 SmartPointer
对象并使用 new Nodo(&(const_cast<T&>(t)))
对其进行了初始化。接下来将这个临时对象复制到 head
中,因此 head
和临时对象都带有相同的非 NULL 指针。现在临时对象被销毁,所以punt
指向的内存被删除但是head
(他的punt
)继续指向被删除的内存区域。现在,您将 head
复制到 tail
中,并且 head
和 tail
都指向同一个删除区域。
看看else案例
tail->next = SmartPointer(new Nodo(&(const_cast<T&>(t))));
tail = tail->next;
在这种情况下,tail->next
(并考虑到 take
指向已删除区域)从删除它的临时对象接收指针。所以你在删除区写了一个指针,马上就删除了。
我希望大家清楚这一切有多危险。
建议:重新设计 SmartPointer
class.
p.s.: 对不起我的英语不好
当我从列表中删除一个元素时,我遇到了这个问题。
这是我的 list.h:
class AwesomeList {
friend class Iteratore;
private:
class Nodo;
class SmartPointer {
public:
Nodo* punt;
SmartPointer(Nodo* n = 0): punt(n) {}
SmartPointer(const SmartPointer& ptr): punt(ptr.punt) {}
~SmartPointer() {
delete punt;
}
SmartPointer& operator=(const SmartPointer& ptr) {
if (this != &ptr) {
delete punt;
punt = ptr.punt;
}
return *this;
}
bool operator==(const SmartPointer& ptr) const {
return ptr.punt == punt;
}
bool operator!=(const SmartPointer& ptr) const {
return ptr.punt != punt;
}
Nodo* operator->() const {
return punt;
}
Nodo& operator*() const {
return *punt;
}
};
class Nodo {
public:
T* value;
SmartPointer next;
Nodo(T* t = T(), const SmartPointer& ptr = SmartPointer()): value(t), next(ptr) {}
};
SmartPointer head;
SmartPointer tail;
public:
class Iteratore{
friend class AwesomeList;
private:
AwesomeList::SmartPointer punt;
public:
bool operator==(const Iteratore& it) const {
return it.punt == punt;
}
bool operator!=(const Iteratore& it) const {
return it.punt != punt;
}
Iteratore& operator++() {
if(punt != 0) punt = punt->next;
return *this;
}
Iteratore& operator++(int) {
if(punt != 0) punt = punt->next;
return *this;
}
T* operator*() const {
if (punt != 0) return punt->value;
}
};
AwesomeList(const SmartPointer& ptr = 0): head(ptr), tail(0) {
if (head != 0) {
SmartPointer p = head;
while (p != 0)
p = p->next;
tail = p;
}
}
AwesomeList(const AwesomeList& list): head(list.head), tail(list.tail) {}
AwesomeList& operator=(const AwesomeList& list) {
head = list.head;
tail = list.tail;
}
int getSize() const {
int count = 0;
SmartPointer p = head;
while (p != 0) {
p = p->next;
count++;
}
return count;
}
bool isEmpty() const {
return getSize() == 0;
}
T* at(int pos) const {
if (pos > -1 && pos < getSize()) {
SmartPointer p = head;
while (pos--) {
p = p->next;
}
return p->value;
} else return 0;
}
void add(const T& t) {
if (head == 0) {
head = SmartPointer(new Nodo(&(const_cast<T&>(t))));
tail = head;
} else {
tail->next = SmartPointer(new Nodo(&(const_cast<T&>(t))));
tail = tail->next;
}
}
void remove(int pos) {
if (pos > -1 && pos < getSize()) {
SmartPointer newHead = head;
SmartPointer p = newHead;
head = 0;
while (pos--) {
add(*p->value);
p = p->next;
}
p = p->next;
while (p != 0) {
add(*p->value);
p = p->next;
}
}
}
void replace(int pos, T* t) {
if (pos > -1 && pos < getSize()) {
SmartPointer p = head;
while (pos--)
p = p->next;
p->value = t;
}
}
void replace(int pos, const T& t) {
if (pos > -1 && pos < getSize()) {
SmartPointer p = head;
while (pos--)
p = p->next;
T& t_obj = const_cast<T&>(t);
p->value = &t_obj;
}
}
Iteratore begin() const {
Iteratore it;
it.punt = head;
return it;
}
Iteratore end() const {
Iteratore it;
it.punt = 0;
return it;
}
T* operator[](const Iteratore& it) const {
return it.punt->value;
}
};
这是我做的测试:
AwesomeList<int> list = AwesomeList<int>();
list.add(1);
list.add(2);
list.add(3);
for (int i = 0; i < list.getSize(); i++)
qDebug() <<*(list.at(i)) <<" ";
list.remove(-1);
for (int i = 0; i < list.getSize(); i++)
qDebug() <<*(list.at(i)) <<" ";
list.remove(2);
for (int i = 0; i < list.getSize(); i++)
qDebug() <<*(list.at(i)) <<" ";
list.replace(0, 5);
qDebug() <<"Replace in posizione 0";
auto cit = list.begin();
for (; cit != list.end(); cit++)
qDebug() <<*(*cit) <<" ";
qDebug() <<"Size";
qDebug() <<list.getSize() <<endl;
这是出现错误的行:
- AwesomeList::Nodo::~Nodo() + 16(真棒list.h:8)
- AwesomeList::SmartPointer::~SmartPointer() + 42(真棒list.h:21)
- AwesomeList::SmartPointer::~SmartPointer() + 21(真棒list.h:22)
感谢您的帮助。谢谢!
更新
我通过改变 SmartPointer 和 Nodo 类 解决了我的问题:
SmartPointer(Nodo* n = 0): punt(n) {
if (punt) punt->references++;
}
SmartPointer(const SmartPointer& ptr): punt(ptr.punt) {
if (punt) punt->references++;
}
~SmartPointer() {
if (punt) {
punt->references--;
if (punt->references == 0) delete punt;
}
}
SmartPointer& operator=(const SmartPointer& ptr) {
if (this != &ptr) {
Nodo* n = punt;
punt = ptr.punt;
if (punt) punt->references++;
if (n) {
n->references--;
if (n->references == 0) delete n;
}
}
return *this;
}
bool operator==(const SmartPointer& ptr) const {
return ptr.punt == punt;
}
bool operator!=(const SmartPointer& ptr) const {
return ptr.punt != punt;
}
Nodo* operator->() const {
return punt;
}
Nodo& operator*() const {
return *punt;
}
};
class Nodo {
public:
T* value;
SmartPointer next;
int references;
Nodo(T* t = T(), const SmartPointer& ptr = SmartPointer()): value(t), next(ptr), references(0) {}
};
抱歉,我不明白你下面的比例 SmartPointer
class。
它带有一个指向 Nodo
和 delete
构造函数的指针。好
但是,如果我没记错的话
(1) 当您使用复制构造函数创建 SmartPointer
时,您从复制的 SmartPointer
复制指针,因此您有两个具有相同值的 punt
的对象;当你销毁这两个对象时,你会在同一个指针上调用 delete
两次;这会使程序崩溃
(2)当你调用operator=
时,复制构造函数也有同样的问题,而且,你没有删除旧的指向值
举例看add()
head = SmartPointer(new Nodo(&(const_cast<T&>(t))));
tail = head;
您创建了一个临时 SmartPointer
对象并使用 new Nodo(&(const_cast<T&>(t)))
对其进行了初始化。接下来将这个临时对象复制到 head
中,因此 head
和临时对象都带有相同的非 NULL 指针。现在临时对象被销毁,所以punt
指向的内存被删除但是head
(他的punt
)继续指向被删除的内存区域。现在,您将 head
复制到 tail
中,并且 head
和 tail
都指向同一个删除区域。
看看else案例
tail->next = SmartPointer(new Nodo(&(const_cast<T&>(t))));
tail = tail->next;
在这种情况下,tail->next
(并考虑到 take
指向已删除区域)从删除它的临时对象接收指针。所以你在删除区写了一个指针,马上就删除了。
我希望大家清楚这一切有多危险。
建议:重新设计 SmartPointer
class.
p.s.: 对不起我的英语不好