【问题标题】:c++ memory error ("double free or corruption") when explicitly calling destructor显式调用析构函数时出现c ++内存错误(“双重释放或损坏”)
【发布时间】:2012-04-23 08:25:07
【问题描述】:

我遇到了“*** glibc detected *** /home/ubuntu[....] : double free or corruption (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;
}

现在,显然我在那里做错了什么。谁能告诉我什么?

【问题讨论】:

  • 对于这种错误,通常值得在 valgrind 下运行以获取有关导致问题的原因的更多信息。 (但我怀疑已经发布的答案是正确的)

标签: c++ memory glibc


【解决方案1】:

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

data[i]->~Class();

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

delete data[i];

【讨论】:

    【解决方案2】:

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

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

    在分配namenew[] 并使用delete name; 删除它时确实存在另一个小问题——两者应该匹配,所以你应该使用delete [] name;。然而,鉴于这是char 的数组,这主要是技术性问题——在这种情况下几乎肯定不会造成问题。如果它是一组具有重要析构函数的对象,则典型的症状是某些(大多数)对象没有被正确销毁(即它们的析构函数不会被调用)。从理论上讲,这只是未定义的行为,所以任何事情都可能发生,但它成为问题根源的真正机会非常渺茫(特别是,正如我所说,在@987654327 数组的情况下@)。

    当然,你真正应该做的是将name 变成std::string 并完全跳过所有废话。

    【讨论】:

    • “另一个是你通过销毁它来重新初始化一个对象,然后立即使用placement new在那里创建一个新对象。”就是这样。它是一个对象列表,所以我在从列表中删除对象“类”时调用析构函数。
    • @Johnsmith:在这种情况下,发布该代码可能是值得的,因此我们可以看到它是如何工作的(或不工作,视情况而定)。
    【解决方案3】:
    data[i]->~Class();
    

    你不应该这样调用析构函数。 delete 如果它是用new 分配的,或者什么都不做,当对象超出范围时将调用析构函数。

    【讨论】:

      猜你喜欢
      • 2021-12-26
      • 2014-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-26
      • 1970-01-01
      • 2020-02-15
      • 1970-01-01
      相关资源
      最近更新 更多