显式调用析构函数时的C++内存错误(“双自由或损坏”)

显式调用析构函数时的C++内存错误(“双自由或损坏”),c++,memory,glibc,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: }; 然后 现

我让***glibc检测到***/home/ubuntu[…]:双重免费或损坏fasttop:0x09851168***问题

调试我找出了问题的根源:

data[i]->~Class();
指的是

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

};
然后


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

你做错的事情是显式调用析构函数:

data[i]->~Class();
除非您完全知道应该显式地调用它,否则这是不寻常的,而且许多大型程序从来没有必要这样做,否则您可能应该使用delete:


你不应该那样调用析构函数。如果为其分配了new,请将其删除,或者什么都不做,当对象超出范围时将调用析构函数。

我只知道在几种情况下使用:data[I]->~Class;。一个是,您正在使用placement new在该位置创建对象。另一种方法是通过销毁对象来初始化对象,然后立即使用placement new在其中创建新对象。这两种方法都是相当先进的技术,坦率地说,非常不寻常,除非您正在创建自己的集合类

我的猜测是1您不需要它,2您没有真正向我们展示重要的代码,这些代码很可能是围绕显式dtor调用的内容

在使用new[]分配名称和使用delete name删除名称时,您还有一个小问题;-两者应该匹配,因此您应该使用delete[]name;。然而,考虑到这是一个字符数组,这主要是一个技术问题——在这种情况下,它几乎肯定不会引起问题。如果是一个包含非平凡析构函数的对象数组,典型的症状是一些大多数对象没有被正确销毁,即它们的析构函数没有被调用。理论上,这只是未定义的行为,所以任何事情都有可能发生,但它成为问题根源的真正机会非常渺茫,特别是,正如我所说的,在字符数组的情况下


当然,您真正应该做的是将name设置为std::string,并完全跳过所有这些废话。

对于此类错误,通常值得在valgrind下运行,以获得有关问题原因的更多信息。但是我怀疑已经发布的答案是正确的。另一个是,你正在通过销毁一个对象来初始化它,然后立即使用placement new在那里创建一个新对象。就是这样。这是一个对象列表,所以当从列表中删除对象类时,我调用析构函数。@Johnsmith:在这种情况下,可能值得发布代码,这样我们就可以看到它是如何工作的或不工作的,视情况而定。
data[i]->~Class();
delete data[i];
data[i]->~Class();