STL 矢量 push_back() 内存双倍可用

STL vector push_back() memory double free

本文关键字:内存 矢量 push back STL      更新时间:2023-10-16

可能的重复项:
什么是三法则?

我在以下程序中遇到了双重释放内存的问题。

调试器显示问题出在push_back()函数中。

A类:

class A {
    public:
        A(int x);
        int x;
};
A::A(int x) {
    this->x = x;
}

B类:

class B {
    public:
        B(int x);
        ~B();
        A* a;
};
B::B(int x) {
    this->a = new A(x);
}
B::~B() {
    delete a;
}

主要功能:

int main() {
    vector<B> vec;
    for(int i = 0; i < 10; i++) {
        vec.push_back(B(i)); <------------ Issue is here
    }
    cout << "adding complete" << endl;
    for(int i = 0; i < 10; i++) {
        cout << "x = " << (vec[i].a)->x << endl;
    }
    return 0;
}

这段代码有什么问题?

编辑:错误double free or memory corruption

你忘了定义复制构造函数和复制赋值运算符,所以你的包装对象正在被一些B delete......然后,当B的某些副本超出范围时。

在这种情况下,它是您确定的行上的临时B(i),以及向量中实现定义的副本数。

遵守三法则。

代码中的问题是由于"纯"C/C++指针没有所有权概念。当指针被复制时,两个副本*都"认为"它们拥有数据,从而导致双重删除。

认识到这一事实,C++标准库的设计者引入了一个unique_ptr<T>类,可以帮助您解决此类问题。


*指针的一个副本位于传递给push_back的实例中 B ;指针的另一个副本位于输入到vector 中的实例中。

注意三法则

其他人都已经对此喋喋不休,所以我不会进一步深入。

要解决您显然试图完成的用法(并在消除过程中符合三法则),请尝试以下操作。虽然每个人都对动态成员所有权的正确管理是绝对正确的,但可以轻松制作您的特定样本以完全避免使用它们。

A类

class A {
    public:
        A(int x);
        int x;
};
A::A(int x) 
   : x(x)
{
}

B类

class B {
    public:
        B(int x);
        A a;
};
B::B(int x) 
    : a(x) 
{
}

主程序

int main() {
    vector<B> vec;
    for(int i = 0; i < 10; i++) {
        vec.push_back(B(i));
    }
    cout << "adding complete" << endl;
    for(int i = 0; i < 10; i++) {
        cout << "x = " << vec[i].a.x << endl;
    }
    return 0;
}

底线除非有充分的理由,否则不要使用动态分配,并且它由包含的变量(如智能指针或大力实践三法则的类)终身保护。