【问题标题】:How concerned should I be about the loss blocked in valgrind我应该多担心在 valgrind 中被阻止的损失
【发布时间】:2011-08-02 09:15:32
【问题描述】:

在我的代码中,我有一个类 lipid,其中包含三个 beads:

struct lipid{
  particle mainPart;
  bead * head;
  bead * body;
  bead * tail;
  int LID;
  vec direction;
  bead * operator[](int index){
    switch(index){
    case 0: return head;
    case 1: return body;
    case 2: return tail;
    default: return body;
    }
  }
};


struct bead{
  particle mainPart;
  int charge;
  int type;
  double rho;
  double nextRho;
  int LID;
  double U;
  double nextU;
  bool touch;
};


struct particle{
  vec pos;
  vec oldPos;
  vec vel;
  vec oldVel;
  vec F;
  vec oldF;
 };

class vec{
  velarry<double> coor;
  double x;
  double y;
  double z;
}

当我尝试创建脂质时,我使用 new 创建了三个珠子

lipid * l = new lipid;
l->head = new bead;
l->body = new bead;
l->tail = new bead;

当我对我的代码进行 valgrind 时,我收到一个错误,声称缺少大量块...我应该对此有多担心?我应该声明我正在将beads 和lipids 推入(几个)向量中。

编辑 好的,添加delete head .. 解决了这个问题,但我仍然有一个疼痛的问题,我有一条线:

this->beadBoxes[t[0]][t[1]][t[2]].push_back(b);

t 是大小为 3 的 vector&lt;int&gt;beadsBoxes 是:

<vector<vector<vector<vector<bead*> > > > beadBoxes;

这家伙给我5次内存泄漏错误:

==22458== 48 bytes in 2 blocks are definitely lost in loss record 11 of 106
==22458==    at 0x4A0666E: operator new(unsigned long) (vg_replace_malloc.c:220)
==22458==    by 0x419A3C: __gnu_cxx::new_allocator<bead*>::allocate(unsigned long, void const*) (new_allocator.h:88)
==22458==    by 0x419A64: std::_Vector_base<bead*, std::allocator<bead*> >::_M_allocate(unsigned long) (stl_vector.h:127)
==22458==    by 0x423E1F: std::vector<bead*, std::allocator<bead*> >::_M_insert_aux(__gnu_cxx::__normal_iterator<bead**, std:\
:vector<bead*, std::allocator<bead*> > >, bead* const&) (vector.tcc:275)
==22458==    by 0x424073: std::vector<bead*, std::allocator<bead*> >::push_back(bead* const&) (stl_vector.h:610)
==22458==    by 0x409664: membrane::updateBox(bead*) (membrane.cpp:874)
==22458==    by 0x40ACA5: membrane::decide(lipid*) (membrane.cpp:793)
==22458==    by 0x40DF01: membrane::rotate() (membrane.cpp:529)
==22458==    by 0x40DFAF: membrane::MCstep() (membrane.cpp:480)
==22458==    by 0x401B54: main (main.cpp:15)

我怀疑这可能与发生的分段错误有关,那就是那条线。为什么会出现 new (unsigned long) 以及为什么会引发分段错误?

【问题讨论】:

  • 嗯 - 你要删除珠子 + 脂质吗?显然,如果你不删除它们,你会得到一个泄漏......
  • 不,它们会一直保存到运行结束。当我只创建脂质(没有珠子)时,没有这样的信息

标签: c++ memory-leaks valgrind


【解决方案1】:

您是否释放了new 分配的对象?

为了获得一致的行为,您应该考虑使用构造函数和析构函数:

struct lipid{
    // constructor
    lipid() {
        this->head = new bead;
        this->body = new bead;
        this->tail = new bead;
    }
    // destructor
    ~lipid() {
        delete this->head;
        delete this->body;
        delete this->tail;
    }
    ... // rest of the class

【讨论】:

    【解决方案2】:

    你当然有泄漏;你没有释放你的记忆。

    在破坏珠子的脂质类中定义一个析构函数,当您将动态分配的脂质存储在向量中时,请使用 RAIIshared_ptr 或类似名称。

    更好的是,使用shared_ptrs 处理所有内容。甚至只使用堆栈;从您给出的设计来看,无论如何都不需要指针(尤其是裸指针)

    【讨论】:

      【解决方案3】:

      您首先不应该使用原始指针。
      使用 Smart pointers & RAII,这是解决您遇到的问题的最佳方法。使用智能指针将确保一旦不再有指针引用对象,对象本身将负责释放。

      看看shared_ptr

      就您发布的源代码而言,您永远不会取消分配动态分配的对象,因此内存泄漏。

      【讨论】:

      • 在没有明显共享的情况下,为什么要推荐 shared_ptr?
      • @daramarak:因为 OP 声明 I should state that I'm pushing the beads and the lipids into (several) vectors.
      • 我错过了那个。所以我明白你的意思。尽管人们应该小心共享所有权,因为在我看来这是很少需要的东西,并且有缺点,尤其是。过度使用。
      【解决方案4】:

      就像其他海报的精彩解释一样,这些丢失的块是已分配但从未释放的内存,因此在您的程序的同一运行中将永远无法再次使用。

      当您尝试运行程序更长的时间并需要许多新的脂质结构时,这是一个明确的问题。从软件工程 POV 来看,您必须释放内存。但是,您似乎是在科学背景下进行编程的,因此我想补充一点,您的结果不受丢失释放的影响,并且从科学家的 POV 来看,您可能可以承受在这里的马虎。

      【讨论】:

        【解决方案5】:

        从您的代码中,我想 Valgrind 试图告诉您的是您有内存泄漏。

        在堆上分配一些对象后:

        lipid * l = new lipid;
        l->head = new bead;
        l->body = new bead;
        l->tail = new bead;
        

        您还应该适当地delete 他们来恢复内存。事实上,你的脂质类缺少一个你清理的析构函数......你可以尝试这样的事情:

        struct lipid{
          particle mainPart;
          bead * head;
          bead * body;
          bead * tail;
          ~lipid() {
              delete head;
              delete body;
              delete tail;
          }
          ...
        };
        

        并像这样使用它:

         lipid * l = new lipid;
        l->head = new bead;
        l->body = new bead;
        l->tail = new bead;
        
        ...
        
        //-- when you are done with lipid:
        delete l;
        

        【讨论】:

        • 为什么,当我不创建珠子而只创建脂质时,没有泄漏?
        • 您在哪里删除了l 脂质?
        • 我不会删除它们,它们会一直保存到运行结束。我向lipid 添加了一个析构函数,它可以工作。我已经向我的问题添加了一个部分,这就是我首先发现此错误的原因
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-16
        • 2018-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多