【问题标题】:C++ destructor runtime error: failed to munmapC++ 析构函数运行时错误:无法 munmap
【发布时间】:2013-08-10 13:36:09
【问题描述】:

我定义了一个名为 ClusterSet 的类,它只有一个字段,名为 clusters

class ClusterSet {
   std::map<std::string, std::map<std::string, float>* > clusters;

   public:
      typedef std::map<std::string, std::map<std::string, float> *>::iterator iterator;
      typedef std::map<std::string, std::map<std::string, float> *>::const_iterator const_iterator;

      iterator begin() { return clusters.begin(); }
      const_iterator begin() const { return clusters.begin(); }
      iterator end() { return clusters.end(); }
      const_iterator end() const { return clusters.end(); }

      void create_cluster(std::string representative);
      void add_member(std::string representative, std::string member, float similarity);
      int write_to_file(std::string outputfile);
      int size();
      ~ClusterSet();
};

在我的create_cluster 方法中,我使用new 为内部映射分配内存,并将此指针存储在clusters 中。我定义了一个析构函数,以便我可以释放所有这些内存:

ClusterSet::~ClusterSet() {
  ClusterSet::iterator clust_it;
  for (clust_it = clusters.begin(); clust_it != clusters.end(); ++clust_it) {
      std::cout << "Deleting members for " << clust_it->first << std::endl;
      delete clust_it->second;
  }
}

当我的析构函数被调用时,它似乎正确地释放了所有内部映射(它为每个映射打印出“删除成员...”)。但是,一旦完成,我会收到一个运行时错误,上面写着“无法“munmap”1068 字节:无效参数”。这是什么原因造成的?

我已经简要地查看了“三法则”,但我不明白为什么我需要一个复制构造函数或一个赋值运算符,或者这可能如何解决我的问题。我永远不需要直接使用任何一个。

【问题讨论】:

  • 即使你不认为你在复制你的对象,你也可能在很多地方。那你将来什么时候做呢?我看不出为什么首先需要该指针的原因,但至少使用智能指针。
  • 请注意,您可以创建私有复制构造函数和赋值运算符,以便编译器可以告诉您“隐藏”副本的制作位置。
  • “我永远不需要直接使用它们”——也许不需要,但编写间接使用它们的代码非常容易。至少,您应该删除它们以防止无效复制。
  • @Lalaland,不过这可能发生在课堂上。你可以使用= delete
  • 另外,“我使用new 为内部映射分配内存。”你到底为什么要那样做?只需存储地图对象,您所有的复制问题都可以通过零规则解决。

标签: c++ destructor memory-management


【解决方案1】:

动态分配内部映射没有充分的理由(也有很多缺点)。将外部地图类型更改为

std::map<std::string, std::map<std::string, float> >

然后您根本不需要实现自己的析构函数和复制/移动语义(除非您想更改从地图中获得的那些,也许是为了防止复制您的类)。

如果在其他情况下,您确实需要存储指向对象的指针并且将它们的生命周期与它们在地图中的存在联系起来,请存储智能指针:

std::map<std::string, std::unique_ptr<something> >

如果您出于某种原因真的想手动管理它们的生命周期,那么您将需要遵循三法则并为您的类提供有效的复制语义(通过删除复制构造函数/赋值运算符来防止复制,或实现任何你想要的语义)。即使您不认为自己在复制对象,也很容易编写这样做的代码。

【讨论】:

    猜你喜欢
    • 2015-09-22
    • 2019-03-06
    • 2017-05-27
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 2020-05-06
    • 1970-01-01
    • 2016-04-02
    相关资源
    最近更新 更多