簡體   English   中英

具有STL向量的C ++內存泄漏

[英]C++ Memory Leak With STL Vector

我在C ++中為數據結構類構建模板化的Max Heap類。 該實現演示了在引擎蓋下帶有向量的Max Heap。 有一個與作業相關的在線提交,當我提交我的作業時,所有測試(推,彈出,頂部和大小)通過並正常工作(對於在線未知單元測試以及我編寫的所有測試),並且我有我的任何測試都沒有內存泄漏,但是我在在線提交中未通過內存泄漏部分,這向我表明我的Bubble Up(重新堆放)或Bubble Down(重新堆放)算法在矢量索引方面做的很有趣。

我注意到我經常使用方括號運算符來弄亂向量,因此我將所有方括號更改為.at()這樣我就可以看到任何抑制的越界錯誤。 除了據稱內存泄漏外,色彩再次飛漲。 然后我很清楚,也許一個單元測試正在添加太多值,向量由於某種未知原因無法清除所有值……不是這種情況,因為我在我的最大堆類中的向量中添加了太多值單元測試花了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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM