繁体   English   中英

如何修复Valgrind内存泄漏?

[英]How to fix Valgrind memory leaks?

我正在尝试实现一个基本的跳过列表,但我无法弄清楚问题是什么,因为当我运行它时它给了我Segmentaion Fault。

我用Valgrind来检查内存泄漏,它给了我一些绝对丢失的BLOCKS错误。

我像这样经营Valgrind:

valgrind --leak-check=full --show-leak-kinds=all -v ./myProgram

我已经尝试删除可删除的内容,但它给了我相同的结果以及其他一些错误。

==20782== HEAP SUMMARY:
==20782==     in use at exit: 96 bytes in 2 blocks
==20782==   total heap usage: 14 allocs, 12 frees, 81,976 bytes allocated
==20782== 
==20782== Searching for pointers to 2 not-freed blocks
==20782== Checked 111,288 bytes
==20782== 
==20782== 48 bytes in 1 blocks are definitely lost in loss record 1 of 2
==20782==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20782==    by 0x1096AA: SkipList<int>::insertID(int, int) (in /home/matei/Desktop/Anul 1/S.D./Tema1/checker_tema1_2019/tema1)
==20782==    by 0x109395: main (in /home/matei/Desktop/Anul 1/S.D./Tema1/checker_tema1_2019/tema1)
==20782== 
==20782== 48 bytes in 1 blocks are definitely lost in loss record 2 of 2
==20782==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20782==    by 0x1096CD: SkipList<int>::insertID(int, int) (in /home/matei/Desktop/Anul 1/S.D./Tema1/checker_tema1_2019/tema1)
==20782==    by 0x109395: main (in /home/matei/Desktop/Anul 1/S.D./Tema1/checker_tema1_2019/tema1)
==20782== 
==20782== LEAK SUMMARY:
==20782==    definitely lost: 96 bytes in 2 blocks
==20782==    indirectly lost: 0 bytes in 0 blocks
==20782==      possibly lost: 0 bytes in 0 blocks
==20782==    still reachable: 0 bytes in 0 blocks
==20782==         suppressed: 0 bytes in 0 blocks
==20782== 
==20782== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==20782== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

SkipList.h

using namespace std;

#define MIN_ID 0
#define MAX_ID 999999
#define NULL_SCORE 0

template < class T >
class Node {
public:
   T level;
   T ID;
   T score;
   Node<T>* next;
   Node<T>* prev;
   Node<T>* below;
   Node<T>* above;

   Node() {
      next = NULL;
      prev = NULL;
      below = NULL;
      above = NULL;
   }

   Node(T ID, T score) {
      this->level = 1;
      this->ID = ID;
      this->score = score;
      next = NULL;
      prev = NULL;
      below = NULL;
      above = NULL; 
   }

   Node(const Node& node) : level(node->level), ID(node->ID), score(node->score) {

   }

   Node& operator=(const Node& node) {
      level = node->level;
      ID = node->ID;
      score = node->score;
      return *this;
   }

   ~Node() {}

   T getScore() {
      return this->score;
   }

   T getID() {
      return this->ID;
   }

   T getLeve() {
      return this->level;
   }

   T setScore(T score) {
      T old_score;
      old_score = this->score;
      this->score = score;
      return old_score;
   }
};

template < class T >
class SkipList {
public:
   Node<T>* head;
   Node<T>* tail;
   Node<T>* p1;
   Node<T>* p2;
   T height;
   T no_entries;

   SkipList() {
      p1 = new Node<T>(MIN_ID, NULL_SCORE);
      p2 = new Node<T>(MAX_ID, NULL_SCORE);
      head = p1;
      tail = p2;
      p1->next = p2;
      p2->prev = p1;
      height = 1;
      no_entries = 0;
   }

   ~SkipList() {
      delete p1;
      delete p2;
   }

   SkipList(const SkipList& SkipList) : height(SkipList->height), no_entries(SkipList->no_entries) {

   }

   SkipList& operator=(const SkipList& SkipList) {
      height = SkipList->height;
      no_entries = SkipList->no_entries;
      return *this;
   }

   T getSize() {
      return this->no_entries;
   }

   T getHeight() {
      return this->height;
   }

   bool isEmpty() {
      if (no_entries == 0) {
         return true;
      }else {
         return false;
      }
   }

   T getScore(T ID) {
      Node<T>* p;
      p = searchID(ID);
      if (p.getID() == ID ) {
         return p->score;
      }else {
         return NULL;
      }
   }

   string coinFlip() {
      string s;
      string str1 = "Heads";
      string str2 = "Tails";
      int r;
      srand(time(0));
      for (int i = 1; i < 2; i++) {
        r = 1 + (rand() %2);
      }
      if (r == 1) {
         s.assign(str1);
      }else if (r == 2) {
         s.assign(str2);
      }
      return s;
   }

   Node<T>* insertAbove(Node<T>* p, Node<T>* e, T ID, T score) {
      e = new Node<T>(ID, score);

      p->above = e;
      e->below = p;

      e->below->prev->above->next = e;
      e->prev = e->below->prev->above;

      e->below->next->above->prev = e;
      e->next = e->below->next->above;

      delete e;
      return e;

   }

   Node<T>* searchID(T ID) {
      Node<T>* p;
      p = head;
      while (p->below != NULL) {
         p = p->below;
         while (ID >= p->next->ID) {
            p = p->next;
         }
      }
      return p;
   }

   Node<T>* insertID(T ID, T score) {
      Node<T>* aux1;
      Node<T>* new_node1 = new Node<T>(ID, score);

      aux1 = searchID(ID);

      aux1->next = new_node1;
      new_node1->prev = aux1;
      new_node1->next = tail;

      while (coinFlip() == "Heads"); {
         if (new_node1->level >= height) {
            height++;
            Node<T>* new_node2 = new Node<T>(ID, score);

            //Create a new empty layer
            Node<T>* p1 = new Node<T>(MIN_ID, NULL_SCORE);
            Node<T>* p2 = new Node<T>(MAX_ID, NULL_SCORE);

            //Making the connections
            head->above = p1;
            tail->above = p2;

            p1->below = head;
            p2->below = tail;

            p1 = head;
            p2 = tail;

            while (aux1->above == NULL) {
               aux1 = aux1->prev;
            }
            aux1 = aux1->above;

            insertAbove(new_node1, new_node2, ID, score);

            new_node1->level++;
            delete new_node2;
         }
      }
      no_entries++;
      delete new_node1;
      return new_node1;
   }

   bool deleteID(T ID) {
      Node<T>* current = head;
      bool found = false;
      if (current->next == NULL && current->next->ID == ID) {
         found = true;
         current->next = current->next->next;
         no_entries--;
      }
      delete current;
      return found;
   }
};

main.cpp中

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

#include "SkipList.h"

using namespace std;
int main() {
   SkipList<int>* my_SkipList = new SkipList<int>();

   for (int i = 0; i < 5; i++) {
      my_SkipList->insertID(i, i);
   }

   return 0;
}

(我假设你添加delete my_SkipList在年底main 。)

如果使用调试信息进行编译,最好不进行优化(选项取决于编译器,通常是-g -O0 ), valgrind显示检测到的问题的行号,如

==23956== 48 bytes in 1 blocks are definitely lost in loss record 1 of 2
==23956==    at 0x4C266E7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23956==    by 0x400E94: SkipList<int>::insertID(int, int) (SkipList.h:194)
==23956==    by 0x400C40: main (main.cpp:13)
==23956== 
==23956== 48 bytes in 1 blocks are definitely lost in loss record 2 of 2
==23956==    at 0x4C266E7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23956==    by 0x400EB7: SkipList<int>::insertID(int, int) (SkipList.h:195)
==23956==    by 0x400C40: main (main.cpp:13)

由此我们可以很容易地看到无与伦比的分配

            //Create a new empty layer
            Node<T>* p1 = new Node<T>(MIN_ID, NULL_SCORE);
            Node<T>* p2 = new Node<T>(MAX_ID, NULL_SCORE);

从这里我们可以找出存在相关错误的地方。

  1. 您不能delete属于现有SkipList节点,即insertAbove()delete einsertID()中的delete new_node1将被删除。

  2. insertID()中插入new_node1的代码

      aux1->next = new_node1; new_node1->prev = aux1; new_node1->next = tail; 

    假设下一个节点总是tail是错误的; 更好:

      new_node1->next = aux1->next; // next isn't necessarily tail aux1->next = new_node1; new_node1->prev = aux1; 
  3. 最重要的是,析构函数~SkipList()只释放构造函数中分配的两个节点是不够的 - 而且之后为SkipList分配的所有节点都必须被释放,例如:

      ~SkipList() { for (Node<T> *p, *c; p = head; ) { head = head->above; do c = p, p = p->next, delete c; while (p); } } 

请注意,这些点仅解决代码中的分配错误,而不解决任何其他逻辑错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM