C++ 内存泄漏与 STL vector

标签 c++ vector memory-leaks stl valgrind

我正在用 C++ 为数据结构类构建模板化最大堆类。该实现演示了一个带有 vector 的最大堆。有一个与作业相关的在线提交,当我提交我的时,所有测试(push、pop、top 和 size)都通过并工作(对于在线未知单元测试以及我编写的所有单元测试)并且我有我的任何测试都没有内存泄漏,但是我在在线提交的内存泄漏部分失败了,这表明我的 Bubble Up (Reheap Up) 或 Bubble Down (Reheap Down) 算法正在对 vector 索引做一些有趣的事情。

我注意到我经常使用括号运算符来弄乱 vector ,所以我仔细检查并将所有括号更改为 .at() 这样我就可以看到任何被抑制的越界错误.再次飞扬,除了据称的内存泄漏。然后我很好地想也许其中一个单元测试添加了太多的值, vector 由于某种未知原因无法全部清除它们...不是这种情况,因为我在我的最大堆类中向 vector 添加了这么多值单元测试需要 90 秒才能完成,在完成所有 52K 分配后,还进行了 52K 释放,并且 valgrind 报告没有错误。

下面是该类的一些主要代码,如果有人可以决定在某些情况下可能会导致内存泄漏的代码的编写位置,那就太好了!

template <class T> 
class MaxHeap {
public: 

MaxHeap(){ 
  // TODO: Fill me in
}

~MaxHeap() {
  data.clear();
}

void push(T value){
  data.push_back(value);
  bubbleUp(data.size()-1, value);
}

void pop(){
  if(!size()) {
    return;
  }
  T val = data.at(size()-1);
  data.pop_back();
  if(!size()) {
    return;
  }
  data.at(0) = val;
  bubbleDown(0, val);
}

T top(){
  if(!data.size()) throw logic_error("Empty Heap");
  return data.at(0);
}

unsigned int size(){
  return data.size();
}

void print_vec() {
  for (int i = 0; i < size(); ++i) {
    cout << data.at(i) << " ";
  }
  cout << endl;
}

vector<T> getVec() {
  return data;
}

private:
  vector<T> data;
  void bubbleUp(int idx, T value) {
    int position = idx;
    int parent_idx = parent(position);

    while (data.at(parent_idx) < value) {
      data.at(position) = data.at(parent_idx);
      data.at(parent_idx) = value;
      position = parent_idx;
      parent_idx = parent(position);
    }
  }

  void bubbleDown(int idx, T value) {
    int left_child_idx = left_child(idx);
    int right_child_idx = right_child(idx);
    int max_child_idx;

    if(left_child_idx <= size()-1) {  // left child (consequently right child) in bounds of vector
      if(left_child_idx == size()-1) { // no right child, left is maxchild
        max_child_idx = left_child_idx;
      } else {
        max_child_idx = (data.at(left_child_idx) <= data.at(right_child_idx)) ? right_child_idx : left_child_idx;
      }

      if(data.at(idx) < data.at(max_child_idx)) {
        data.at(idx) = data.at(max_child_idx);
        data.at(max_child_idx) = value;
        bubbleDown(max_child_idx, value);
      }
    }
  }

  int left_child(int idx) {return (idx*2+1);}
  int right_child(int idx) {return (idx*2+2);}
  int parent(int idx) {return ((idx-1)/2);}

};

最佳答案

警告:这只是一种理论,因为泄漏源不太可能出现在此处显示的代码中。

如果 T 是格式错误的类型,在使用赋值运算符时不会释放它的内存,那么这可能是触发此不良行为的部分:

T swap; // initialized to something. perhaps using new

while (data.at(parent_idx) < value) {
  swap = data.at(parent_idx); //assume no delete in T.operator=()
  data.at(parent_idx) = value;
  data.at(position) = swap;
  position = parent_idx;
  parent_idx = parent(position);
}

这在这段代码 中不是问题。但是,您仍然可以在此处对其进行修补。为什么 T 定义在循环外?

while (data.at(parent_idx) < value) {
  T swap = data.at(parent_idx); // no assignment here
  data.at(parent_idx) = value;
  data.at(position) = swap;
  position = parent_idx;
  parent_idx = parent(position);
}

===

不相关但更好 - 不要使用不必要的中间变量,并混入移动语义:

while (data.at(parent_idx) < value) {
  data.at(position) = std::move(data.at(parent_idx));
  data.at(parent_idx) = value;
  position = parent_idx;
  parent_idx = parent(position);
}

关于C++ 内存泄漏与 STL vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33818063/

相关文章:

r - 复制R中的向量

c++ - vector 的元素突然变得未初始化

c++ - VC 2012中的内存泄漏检测

c++ - 如何找到内存泄漏的位置?

c++ - Trimesh - 泄漏内存

c++ - 模板非类型参数和分配数组内存

c++ - google mock - 如何模拟被测类拥有的对象

c++ - 错误 : cannot open file 'boost_atomic-vc120-mt-1_58.lib' boost libs on Qt Windows8

c++ - 我想知道在调试时指针拥有特定的地址

c++ - 如何删除不断改变其大小的 vector 的一系列元素(C++)?