未分配正在释放的指针 - 析构函数
Pointer being freed was not allocated - destructor
慢慢学习 copy/move 构造函数,规则 5 等。加上对 pointers/reference 的用法不太了解,我无法理解为什么我的析构函数会抛出以下错误。我知道是只有析构函数和析构函数引起的,并且在拷贝构造函数之后。
untitled(19615,0x104a60580) malloc: *** error for object 0x600000b74000: pointer being freed was not allocated
untitled(19615,0x104a60580) malloc: *** set a breakpoint in malloc_error_break to debug
代码:
#include <string>
using namespace std;
typedef int size_type;
class user{
public:
user():
rank(1),
name("default"){
}
private:
int rank;
string name;
};
class account{
public:
account(size_type max_size):
owners(new user[max_size]),
max_size(max_size){
cout<<"normal constructor"<<endl;
}
account(account& other):
owners(other.owners),
max_size(sizeof(owners)){
cout<<"copy constructor called"<<endl;
}
account(account&& other):
owners(other.owners),
max_size(sizeof(owners)){
cout<<"move constructor called"<<endl;
}
~account(){
if(owners!= NULL) {
delete[] owners;
owners= 0;
}
cout<<"destructor called"<<endl;
}
private:
user* owners;
size_type max_size;
};
int main(){
account f(3);
account n(f);
}
I cannot understand why my destructor throws the error below. I know that it's caused by destructor and destructor only
account f(3);
这个对象的构造函数分配了一个数组。
account n(f);
您编写的复制构造函数复制指向动态数组的指针。
n
先被销毁。它的析构函数删除数组。 f
之后被销毁。它的析构函数也删除了相同的数组,并且程序的行为是未定义的,这导致了您观察到的输出。
为了防止分配被多次删除,您必须强制执行 class 不变量(适用于所有成员函数的 post 条件)任何 non-null owners
值在 class 的所有实例中必须是唯一的。要在复制构造函数(以及移动构造函数和复制和移动赋值运算符)中保持不变,您不能像现在那样复制指针。我建议学习RAII成语。
更好的解决方案:不要使用拥有裸指针。使用 std::vector<user>
并且根本没有用户定义的特殊成员函数。
P.S。复制构造函数应该接受对 const.
的引用
还有:
if(owners!= NULL) {
delete[] owners;
owners= 0;
}
检查是多余的,因为删除 null 是安全的。该赋值是多余的,因为该对象即将被销毁并且之后无论如何都无法访问该成员。
慢慢学习 copy/move 构造函数,规则 5 等。加上对 pointers/reference 的用法不太了解,我无法理解为什么我的析构函数会抛出以下错误。我知道是只有析构函数和析构函数引起的,并且在拷贝构造函数之后。
untitled(19615,0x104a60580) malloc: *** error for object 0x600000b74000: pointer being freed was not allocated
untitled(19615,0x104a60580) malloc: *** set a breakpoint in malloc_error_break to debug
代码:
#include <string>
using namespace std;
typedef int size_type;
class user{
public:
user():
rank(1),
name("default"){
}
private:
int rank;
string name;
};
class account{
public:
account(size_type max_size):
owners(new user[max_size]),
max_size(max_size){
cout<<"normal constructor"<<endl;
}
account(account& other):
owners(other.owners),
max_size(sizeof(owners)){
cout<<"copy constructor called"<<endl;
}
account(account&& other):
owners(other.owners),
max_size(sizeof(owners)){
cout<<"move constructor called"<<endl;
}
~account(){
if(owners!= NULL) {
delete[] owners;
owners= 0;
}
cout<<"destructor called"<<endl;
}
private:
user* owners;
size_type max_size;
};
int main(){
account f(3);
account n(f);
}
I cannot understand why my destructor throws the error below. I know that it's caused by destructor and destructor only
account f(3);
这个对象的构造函数分配了一个数组。
account n(f);
您编写的复制构造函数复制指向动态数组的指针。
n
先被销毁。它的析构函数删除数组。 f
之后被销毁。它的析构函数也删除了相同的数组,并且程序的行为是未定义的,这导致了您观察到的输出。
为了防止分配被多次删除,您必须强制执行 class 不变量(适用于所有成员函数的 post 条件)任何 non-null owners
值在 class 的所有实例中必须是唯一的。要在复制构造函数(以及移动构造函数和复制和移动赋值运算符)中保持不变,您不能像现在那样复制指针。我建议学习RAII成语。
更好的解决方案:不要使用拥有裸指针。使用 std::vector<user>
并且根本没有用户定义的特殊成员函数。
P.S。复制构造函数应该接受对 const.
的引用还有:
if(owners!= NULL) { delete[] owners; owners= 0; }
检查是多余的,因为删除 null 是安全的。该赋值是多余的,因为该对象即将被销毁并且之后无论如何都无法访问该成员。