【问题标题】:Memory leaks in my program; is the destructor not getting called?我的程序内存泄漏;析构函数没有被调用吗?
【发布时间】:2017-02-18 23:36:44
【问题描述】:

我觉得我在用头撞砖墙。

我不确定析构函数是否真的被调用了。我正在使用 priority_queue 来保存一堆节点。每个节点都有一个成员 m_grid,它是一个二维结构数组。这个网格代表了我在程序中明确使用的唯一指针。

由于某种原因,我得到了很多泄漏。你能帮帮我吗?

这是析构函数:

grid::~grid()
{
  for (int i = 0; i < m_width; i++)
  {
    delete[] m_grid[i];
    m_grid[i] = NULL;
  }

  delete[] m_grid;
  m_grid = NULL;
}

赋值运算符:

grid& grid::operator=(const grid& g)
{
  m_x_rad = g.m_x_rad;
  m_y_rad = g.m_y_rad;
  m_width = g.m_width;
  m_height = g.m_height;
  m_orientation = g.m_orientation;

  if (m_width != 0)
    m_grid = new cell* [m_width];

  // from left to right
  for (int i = 0; i < m_width; i++)
  {
    m_grid[i] = new cell [m_height];

    // from top to bottom
    for (int j = 0; j < m_height; j++)
    {
      m_grid[i][j].m_occupied = g.m_grid[i][j].m_occupied;
      m_grid[i][j].m_rad = g.m_grid[i][j].m_rad;
    }
  }

  return *this;
}

赋值运算符与预期相似。 最后,这是一些 valgrind 的输出(有很多,但都与 grid::setSize() 或 grid::operator= 有关。

==13329== 200 (40 direct, 160 indirect) bytes in 1 blocks are definitely lost in loss record 25 of 166
==13329==    at 0x4C2E80F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13329==    by 0x4020C1: grid::operator=(grid const&) (grid.cpp:192)
==13329==    by 0x40A02E: node::operator=(node const&) (node.cpp:129)
==13329==    by 0x4075A6: __push_heap<__gnu_cxx::__normal_iterator<node*, std::vector<node> >, long int, node, __gnu_cxx::__ops::_Iter_comp_val<std::greater<node> > > (stl_heap.h:135)
==13329==    by 0x4075A6: push_heap<__gnu_cxx::__normal_iterator<node*, std::vector<node> >, std::greater<node> > (stl_heap.h:199)
==13329==    by 0x4075A6: push (stl_queue.h:502)
==13329==    by 0x4075A6: aStarGraphSearch(basic_map const&, node&, std::unordered_map<int, basic_node, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, basic_node> > >&, std::priority_queue<node, std::vector<node, std::allocator<node> >, std::greater<node> >&) (main_functions.cpp:216)
==13329==    by 0x4088ED: search(int) (main_functions.cpp:706)
==13329==    by 0x401AAA: main (main.cpp:13)

我在这里真的很挣扎。当我使用堆栈而不是优先级队列时,我没有遇到这些问题。任何帮助表示赞赏。

【问题讨论】:

  • 如果没有minimal reproducible example,就不可能有权威的答案,但很明显,复制构造函数无法销毁现有的动态分配的类成员,因此会导致内存泄漏。
  • operator= 正在分配内存而不删除旧内存。这是故意的吗?
  • 如果允许,请使用std::vector&lt;std::vector&lt;cell&gt;&gt; 而不是cell** 来捕获网格。
  • @GregKikola 我不知道我明白你的意思。在使用优先级队列时,我创建了一个新节点,它等于顶部节点。这会调用operator=,但我需要保留原件和副本。
  • @RSahu:甚至没有;使用std::vector&lt;cell&gt; 和覆盖二维索引的封装类型。

标签: c++ memory-leaks valgrind destructor


【解决方案1】:

您不会在赋值运算符中删除 m_grid(及其包含的数组)。

【讨论】:

  • 如果我删除m_grid,我以后就不能再访问网格了……对吧?
  • @hockeysaint 没错。但是,如果不删除它,就会发生内存泄漏。
  • 哦,我误会了。如果我错了,请纠正我,但现在我意识到将m_grid 指向new cell* 会留下m_grid 指向的任何内容。我以为你的意思是我应该删除新创建的m_grid
【解决方案2】:

对赋值运算符的调用不会首先自动调用析构函数。如果您要用新内存替换它,您必须自己清理该对象已经拥有的所有内存。

赋值不会生成新对象;它只是修改了你已经拥有的对象。

【讨论】:

  • 当然,但据我所知,node top_node = frontier.top();(边界是我的队列)应该使top_nodefrontier.top() 完全相同。
  • @hockeysaint:这不会调用赋值运算符。这是一个初始化,而不是一个赋值。
猜你喜欢
  • 2017-01-13
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 1970-01-01
  • 2014-09-22
  • 2011-12-25
  • 2013-11-28
相关资源
最近更新 更多