显式调用析构函数时的c ++内存错误(“双重释放或损坏”)

时间:2012-04-11 02:23:37

标签: c++ memory glibc

我正在检测" * glibc / home / ubuntu [....]:双免费或损坏(fasttop):0x09851168 * *"问题

调试我找出了似乎是问题根源的一行:

data[i]->~Class();

指的是

 class Class {
public:
    Class();
    Class(char *name, double value);
    virtual ~Class();
    char *name;
    double value;
private:

};

然后

    Class::Class() {
}

Class::Class(char* name, double value){
    this->name = new char[std::strlen(name)];
    std::strcpy(this->name, name);
    this->value = value;
}

Class::~Class() {
    delete name;
}

现在,显然我在那里做错了什么。任何人都可以告诉我什么?

3 个答案:

答案 0 :(得分:7)

你做错的事情是明确地调用析构函数:

data[i]->~Class();

除非你绝对知道你应该明确地调用它(这是不寻常的,并且许多大型程序永远不需要这样做),你可能应该使用delete

delete data[i];

答案 1 :(得分:1)

data[i]->~Class();

你永远不应该像这样调用析构函数。 delete如果它被分配了new,或者什么也不做,当对象超出范围时将调用析构函数。

答案 2 :(得分:1)

我只知道您使用的几种情况:data[i]->~Class();。一个是您使用placement new在该位置创建对象。另一个是你通过销毁它来重新初始化一个对象,然后立即使用placement new来在那里创建一个新对象。这些都是相当高级技术,坦率地说,相当不寻常,除非您正在创建自己的集合类。

我的猜测是1)你不需要那个,2)你没有真正向我们展示重要的代码(这很可能是围绕显式dtor调用的东西)。

使用name分配new[]时会遇到另外一个小问题,并使用delete name;将其删除 - 两者应匹配,因此您应该使用{{1} }。鉴于这是delete [] name;的数组,然而,这主要是技术性的 - 在这种情况下几乎肯定不会引起问题。如果它是具有非平凡析构函数的对象数组,则典型的症状是某些(大多数)对象未被正确销毁(即,它们的析构函数不会被调用)。理论上它只是未定义的行为,所以任何都可以发生,但它作为你的问题根源的真正机会极其遥远(特别是,正如我所说,在{{{ 1}})。

当然,你真正应该做的是char一个char并完全忽略所有废话。