简体   繁体   中英

Memory leak on a “return new node” and i can't find a way to fix it

Got a problem with a function that returns a "new node" and I can't find it. Here's the function:

node* append_new_node(node* l, const T& tt) {
    if (l == 0)
        return new node(0, tt);

    node* n = l;
    while (n->next != 0) {
        if (cmp(n->key, tt)) {
            int a= n->counter;
            a++;
            n->counter=a;

            n=0;
            delete n;
            return 0;
        }
        else {
            n = n->next;
        }
    }

    //check per evitare ripetizioni fra numeri uguali consecutivi
    if (!cmp(n->key, tt)){
        n->next = new node(0, tt);
    }
    else {
        n->counter = n->counter+1;
        n=0;
        delete n;
        return 0;
    }
    n=0;
    delete n;
    return l;
}

valgrind report:

==2481== HEAP SUMMARY:
==2481==     in use at exit: 480 bytes in 16 blocks
==2481==   total heap usage: 81 allocs, 65 frees, 2,440 bytes allocated
==2481== 
==2481== Searching for pointers to 16 not-freed blocks
==2481== Checked 193,240 bytes
==2481== 
==2481== 96 (32 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record 6 of 10
==2481==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2481==    by 0x404039: huffman<Color, CaseInsensitiveCmp>::append_new_node(huffman<Color, CaseInsensitiveCmp>::node*, Color const&) (huffman.h:311)
==2481==    by 0x402D61: huffman<Color, CaseInsensitiveCmp>::node* huffman<Color, CaseInsensitiveCmp>::build_list<std::_List_iterator<Color> >(std::_List_iterator<Color>, std::_List_iterator<Color>, unsigned int&) (huffman.h:344)
==2481==    by 0x402283: huffman<Color, CaseInsensitiveCmp>::huffman<std::_List_iterator<Color> >(std::_List_iterator<Color>, std::_List_iterator<Color>) (huffman.h:103)
==2481==    by 0x4016F5: do_test() (main.cpp:137)
==2481==    by 0x401BCB: main (main.cpp:192)
==2481== 
==2481== 96 (32 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record 7 of 10
==2481==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2481==    by 0x404039: huffman<Color, CaseInsensitiveCmp>::append_new_node(huffman<Color, CaseInsensitiveCmp>::node*, Color const&) (huffman.h:311)
==2481==    by 0x402D61: huffman<Color, CaseInsensitiveCmp>::node* huffman<Color, CaseInsensitiveCmp>::build_list<std::_List_iterator<Color> >(std::_List_iterator<Color>, std::_List_iterator<Color>, unsigned int&) (huffman.h:344)
==2481==    by 0x402389: void huffman<Color, CaseInsensitiveCmp>::reset<std::_List_iterator<Color> >(std::_List_iterator<Color>, std::_List_iterator<Color>) (huffman.h:112)
==2481==    by 0x40186F: do_test() (main.cpp:151)
==2481==    by 0x401BCB: main (main.cpp:192)
==2481== 
==2481== 96 (32 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record 8 of 10
==2481==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2481==    by 0x404039: huffman<Color, CaseInsensitiveCmp>::append_new_node(huffman<Color, CaseInsensitiveCmp>::node*, Color const&) (huffman.h:311)
==2481==    by 0x403363: huffman<Color, CaseInsensitiveCmp>::node* huffman<Color, CaseInsensitiveCmp>::build_list<huffman<Color, CaseInsensitiveCmp>::const_iterator>(huffman<Color, CaseInsensitiveCmp>::const_iterator, huffman<Color, CaseInsensitiveCmp>::const_iterator, unsigned int&) (huffman.h:344)
==2481==    by 0x4023F4: huffman<Color, CaseInsensitiveCmp>::huffman(huffman<Color, CaseInsensitiveCmp> const&) (huffman.h:86)
==2481==    by 0x401936: do_test() (main.cpp:159)
==2481==    by 0x401BCB: main (main.cpp:192)
==2481== 
==2481== 96 (32 direct, 64 indirect) bytes in 1 blocks are definitely lost in loss record 9 of 10
==2481==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2481==    by 0x404039: huffman<Color, CaseInsensitiveCmp>::append_new_node(huffman<Color, CaseInsensitiveCmp>::node*, Color const&) (huffman.h:311)
==2481==    by 0x403363: huffman<Color, CaseInsensitiveCmp>::node* huffman<Color, CaseInsensitiveCmp>::build_list<huffman<Color, CaseInsensitiveCmp>::const_iterator>(huffman<Color, CaseInsensitiveCmp>::const_iterator, huffman<Color, CaseInsensitiveCmp>::const_iterator, unsigned int&) (huffman.h:344)
==2481==    by 0x4023F4: huffman<Color, CaseInsensitiveCmp>::huffman(huffman<Color, CaseInsensitiveCmp> const&) (huffman.h:86)
==2481==    by 0x4024B7: huffman<Color, CaseInsensitiveCmp>::operator=(huffman<Color, CaseInsensitiveCmp> const&) (huffman.h:135)
==2481==    by 0x401AEC: do_test() (main.cpp:183)
==2481==    by 0x401BCB: main (main.cpp:192)
==2481== 
==2481== 96 (24 direct, 72 indirect) bytes in 1 blocks are definitely lost in loss record 10 of 10
==2481==    at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2481==    by 0x40398D: huffman<int, IntCmp>::append_new_node(huffman<int, IntCmp>::node*, int const&) (huffman.h:311)
==2481==    by 0x402687: huffman<int, IntCmp>::node* huffman<int, IntCmp>::build_list<std::_List_iterator<int> >(std::_List_iterator<int>, std::_List_iterator<int>, unsigned int&) (huffman.h:344)
==2481==    by 0x402021: huffman<int, IntCmp>::huffman<std::_List_iterator<int> >(std::_List_iterator<int>, std::_List_iterator<int>) (huffman.h:103)
==2481==    by 0x40151A: dotest_iterators() (main.cpp:113)
==2481==    by 0x401BD0: main (main.cpp:193)
==2481== 
==2481== LEAK SUMMARY:
==2481==    definitely lost: 152 bytes in 5 blocks
==2481==    indirectly lost: 328 bytes in 11 blocks
==2481==      possibly lost: 0 bytes in 0 blocks
==2481==    still reachable: 0 bytes in 0 blocks
==2481==         suppressed: 0 bytes in 0 blocks
==2481== 
==2481== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)
==2481== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)
samu@Samu-MS-7821:~/Desktop/test$ 

I'll copy now also other classes named by valgrind

  template <typename InIter>
node* build_list(InIter from, InIter to, unsigned int& sz){
unsigned int n = 0;
node* h = 0;
while (from != to) {
  node* tmp;
  try {

tmp = append_new_node(h, *from);

  } catch(...) {
free_nodes(h);
throw;
  }
  if (tmp != 0) {
++n;
h = tmp;
  }
  ++from;
  tmp=0;
  delete tmp;
}
sz = n;

//creo un array di frequenze
int frequenze[sz];
node* scor=h;
int i=0;
while(scor!=0){
    int prova=scor->counter;
    frequenze[i]=prova;
    i++;
    scor=scor->next;
}



//ordino array
insertion_sort(frequenze,sz);


//creo lista ordinata+assegno codifica
node* coded = 0;
string endcode="1";
string midcode="\n";
string code;
for(int q=sz-1;q>=0;q--){
        node* temp;
        code=(midcode+endcode);
         try {
            temp = append_new_node_c(coded, find_freq(h,frequenze[q]), code);
            //std::cout<<frequenze[q]<<"\n";
        } catch(...) {
            free_nodes(h);
            throw;
        }
        coded=temp;
        if(q-1<=0){
            endcode="0";
        }
        else{
            midcode=midcode+"0";
        }

}

h=0;
scor=0;
delete h;
delete scor;

return coded;}

another function

huffman(const huffman& v)
: head(0), sz(0), cmp(v.cmp){
head = build_list(v.begin(), v.end(), sz);}

Really guys, it would be awesome if someone could help me. I cant really find whhat i have to free or delete to prevent this memory leak. I dont copy all the code cause is about 300 line, but if you need it i will.

Here is the main

int main(){ 
try {
do_test();
dotest_iterators();
std::cout << "ok\n";} 
catch (std::exception& e){
std::cerr << e.what() << std::endl;}
return 0;}

class Color{
public:
Color(int r, int g, int b): red(r), green(g), blue(b){}

void print(std::ostream& os) const{
os << "Color("
   << red << ", "
   << green << ", "
   << blue << ")";}

bool operator==(const Color& c) const {
return red == c.red && green == c.green && blue == c.blue;}

bool operator!=(const Color& c) const {
return !operator==(c);
}

private:
int red;
int green;
int blue;
};


/* Stampa un'istanza di Color. */
std::ostream& operator<<(std::ostream& os,
         const Color& c){
c.print(os);
return os;}


struct CaseInsensitiveCmp{

bool operator()(const Color& a, const Color& b) const{
return a==b;}
};


struct IntCmp{

bool operator()(const int& a, const int& b) const{
return a==b;
}
};



void dotest_iterators(){

typedef IntCmp IntCompare;

std::list<int> lista;
int a,b,c,d,e,f,g,h;
a=1;
b=2;
c=2;
d=1;
e=1;
f=7;
g=1;
h=6;

lista.push_front(a);
lista.push_front(b);
lista.push_front(c);
lista.push_front(d);
lista.push_front(e);
lista.push_front(f);
lista.push_front(g);
lista.push_front(h);

//test sul codice
//std::equal_to<int>

huffman<int, IntCompare > codHuff(lista.begin(),lista.end());
//std::cout << codHuff.size() << "\n";
assert(codHuff.size()==4);

//test valori di codifica
codHuff.find(1);
codHuff.find(2);
codHuff.find(6);
codHuff.find(7);}

void do_test(){

typedef CaseInsensitiveCmp ColorCompare;

std::list<Color> lista2;
//creazione lista e test funzione stampa e size
lista2.push_front(Color(255, 0, 0));
lista2.push_front(Color(0, 255, 0));
lista2.push_front(Color(0, 0, 255));
lista2.push_front(Color(255, 0, 0));

huffman<Color, ColorCompare > codHuff2(lista2.begin(),lista2.end());
assert(codHuff2.size()==3);

codHuff2.find(Color(255, 0, 0));
codHuff2.find(Color(0, 255, 0));
codHuff2.find(Color(0, 0, 255));

std::list<Color> lista3;

lista3.push_front(Color(0, 255, 0));
lista3.push_front(Color(0, 0, 255));
lista3.push_front(Color(255, 0, 0));

//funzione reset
codHuff2.reset(lista3.begin(),lista3.end());
assert(codHuff2.size()==3);

codHuff2.find(Color(255, 0, 0));
codHuff2.find(Color(0, 255, 0));
codHuff2.find(Color(0, 0, 255));

//copy constructor
huffman<Color, ColorCompare > codHuff3(codHuff2);
assert(codHuff2.size() == codHuff3.size());

codHuff3.find(Color(255, 0, 0));
codHuff3.find(Color(0, 255, 0));
codHuff3.find(Color(0, 0, 255));


try {
codHuff2.find(Color(0, 3, 255));
assert(0);
} catch(element_not_found&) {
}

//clear
codHuff3.clear();
assert(codHuff3.size()==0);

//swap
codHuff2.swap(codHuff3);
assert(codHuff2.size()==0);
assert(codHuff3.size()==3);

//assegnamento
codHuff2=codHuff3;
assert(codHuff2.size()==3);}

I hope u guys can help me

Update: I'll put the all code right here:

#ifndef fuffman_h

#include <stdexcept>
#include <iterator>
#include <cassert>
#include <string>
#include <iostream>
#include <exception>

 using namespace std;
/** Versione 2: introduzione degli iteratori. */



/**
 * Eccezione lanciata quando si cerca di inserire una chiave gia'
 * presente.
 */
struct duplicated_element : std::runtime_error
{
  duplicated_element() : std::runtime_error("Duplicated Element") { }
};

/**
 * Eccezione lanciata quando nussuna delle coppie memorizzate
 * corrisponde alla chiave rischiesta.
 */
struct element_not_found : std::runtime_error
{
  element_not_found() : std::runtime_error("Element not found") { }
};


/**
 * Struttura contenente le coppie chiave/valore. NON NECESSARIA?
 */

 /*
template <typename K, typename T>
struct key_value_pair
{
  key_value_pair(const K& kk, const T& vv) : key(kk), value(vv) { }

  template <typename K1, typename T1>
  key_value_pair(const key_value_pair<K1, T1>& p) : key(p.key), value(p.value) { }

  K key;
  T value;
};
*/


/**
 * Un vettore associativo.
 *
 * Contiene coppie chiave/valore di tipo K e T, rispettivamente. Non
 * e' possibile inserire piu' coppie con chiave equivalenti.
 * L'equivalenza tra le chiavi e' definita tramite un funtore
 * specificato dall'utente.
 */
template <typename T, typename Cmp>
class huffman
{
public:

//  typedef key_value_pair<K, T> pair;

  /**
   * Costruttore di default.
   *
   * Il vettore associativo risultante e' vuoto.
   */
  huffman() : head(0), sz(0), cmp() { }

  explicit huffman(const Cmp& c) : head(0), sz(0), cmp(c) { }

  /**
   * Copy constructor.
   *
   * In questa versione l'ordine interno delle copie memorizzate
   * risulta invertito.
   */
  huffman(const huffman& v)
    : head(0), sz(0), cmp(v.cmp)
  {
    head = build_list(v.begin(), v.end(), sz);
  }


  template<typename T1, typename Cmp1>
  huffman(const huffman<T1, Cmp1>& v)
    : head(0), sz(0), cmp()
  {
    head = build_list(v.begin(), v.end(), sz);
  }


  //La funzione prende in ingresso due iteratori puntanti a inizio e fine di una lista e ne creano l'array
  template <typename InIter>
  huffman(InIter from, InIter to)
    : head(0), sz(0), cmp()
  {
    head = build_list(from, to, sz);    
  }

  template <typename InIter>
  void reset(InIter from, InIter to)
    //: head(0), sz(0), cmp()
  {
    if(head!=0){
    clear();}
    head = build_list(from, to, sz);    
  }

  template <typename InIter>
  huffman(InIter from, InIter to, const Cmp& c)
    : head(0), sz(0), cmp(c)
  {
    head = build_list(from, to, sz);    
  }

  /**
   * Distruttore.
   */
  ~huffman()
  {
    free_nodes(head);
  }

  /**
   * Operatore di assegnamento.
   */
  huffman& operator=(const huffman& v)
  {
    huffman tmp(v);
    swap(tmp);
    return *this;
  }

  template<typename T1, typename Cmp1>
  huffman& operator=(const huffman<T1, Cmp1>& v)
  {
    huffman tmp(v);
    swap(tmp);
    return *this;
  }



  //???

  /*
  template <typename InIter>
  void assign(InIter from, InIter to)
  {
    huffman tmp(from, to);
    swap(tmp);
  }
    */


  /**
   * Inserisce una nuova coppia nel vettore.
   *
   * Lancia l'eccezione duplicated_element Nel caso in cui la chiave sia
   * gia' presente.
   */

   //E'  UTILE AI FINI DEL PROGETTO? ELEIMINARE O SPOSTARE IN PRIVATE?
   //PER ORA LA TOLGO

  /*
  void insert(const T& t)
  {
    node* r = append_new_node(head, t);
    if (r == 0)
      throw duplicated_element();
    head = r;
    ++sz;
  }
  */

  /**
   *Stampa codifica, dato un elemento.
   *
   * Lancia l'eccezione element_not_found se nessun elemento corrisponde
   * alla chiave specificata.
   */


  void find(const T& t)
  {
    node* n = find_code(head, t);
    if (n == 0)
      throw element_not_found();
    n=0;
    delete n;
  }


  /**
   * Rimuove la coppia corrispondente alla chiave specificata.
   *
   * Lancia l'eccezione element_not_found se nessun elemento corrisponde
   * alla chiave specificata.
   */


   //E' UTILE AI FINI DEL PROGETTO? ELIMINARE O SPOSTARE IN PRIVATE???
   //PER ORA LA TOLGO

  /*
  void erase(const T& t)
  {
    node* n = find_node(head, t);
    if (n == 0)
      throw element_not_found();
    --sz;
    head = erase_node(head, n);
  }
  */

  /**
   * Restituisce il numero di coppie memorizzate.
   */
  unsigned int size() const
  {
    return sz;
  }

  /**
   * Svuota il vettore associativo.
   */
  void clear()
  {
    huffman tmp;
    swap(tmp);
  }

  /**
   * Scambia il contenuto di due vettori associativi.
   */
  void swap(huffman& v) {
    node* tmp = head; head = v.head; v.head = tmp;
    unsigned int tmps = sz;
    sz = v.sz;
    v.sz = tmps;
    Cmp tmpc = cmp;
    cmp = v.cmp;
    v.cmp = tmpc;
  }

private:

  // L'implementazione si basa su una lista a link singolo.  

  struct node {
    node(node* n, const T& tt) : key(tt), counter(1), codifica(""), next(n){ }
    node(node* n, const T& tt, string c) : key(tt), counter(0), codifica(c), next(n){ }
    T key;
    int counter;
    string codifica;
    node* next;
  };


  node* head;  // Puntatore alla testa della lista
  unsigned int sz;  // Numero di coppie memorizzate
  Cmp cmp;  // funtore di confronto tra chiavi


  // Inserisce p in testa alla lista l. Restituisce il nuovo nodo. MI SERVE?
  node* insert_node(node* l, const T& tt)
  {
    node* ret = new node(l, tt);
    return ret;
  }

  //Appendo con codifica
    node* append_new_node_c(node* l, const T& tt, string c)
  {
    if (l == 0)
      return new node(0, tt, c);

    node* n = l;
    while (n->next != 0) {
      if (cmp(n->key, tt)) {
        int a= n->counter;
        a++;
        n->counter=a;
      n=0;
      delete n;
    return 0;}
    else{
      n = n->next;
      }
    }

    //check per evitare ripetizioni fra numeri uguali consecutivi
    if (!cmp(n->key, tt)){
    n->next = new node(0, tt, c);}
    else{
    n->counter=n->counter+1;
    n=0;
    delete n;
    return 0;}
    n=0;
    delete n;
    return l;
  }


  // Append
  node* append_new_node(node* l, const T& tt)
  {
    if (l == 0)
      return new node(0, tt);

    node* n = l;
    while (n->next != 0) {
      if (cmp(n->key, tt)) {
        int a= n->counter;
        a++;
        n->counter=a;
    n=0;
    delete n;
    return 0;}
    else{
      n = n->next;
      }
    }

    //check per evitare ripetizioni fra numeri uguali consecutivi
    if (!cmp(n->key, tt)){
    n->next = new node(0, tt);}
    else{
    n->counter=n->counter+1;
    n=0;
    delete n;
    return 0;}
    n=0;
    delete n;
    return l;
  }


  //implementa qua merge e codifica
  template <typename InIter>
  node* build_list(InIter from, InIter to, unsigned int& sz)
  {
    unsigned int n = 0;
    node* h = 0;
    while (from != to) {
      node* tmp;
      try {

    tmp = append_new_node(h, *from);

      } catch(...) {
    free_nodes(h);
    throw;
      }
      if (tmp != 0) {
    ++n;
    h = tmp;
      }
      ++from;
    tmp=0;
    delete tmp;
    }
    sz = n;

    //creo un array di frequenze
    int frequenze[sz];
    node* scor=h;
    int i=0;
    while(scor!=0){
        int prova=scor->counter;
        frequenze[i]=prova;
        i++;
        scor=scor->next;
    }



    //ordino array
    insertion_sort(frequenze,sz);


    //creo lista ordinata+assegno codifica
    node* coded = 0;
    string endcode="1";
    string midcode="\n";
    string code;
    for(int q=sz-1;q>=0;q--){
            node* temp;
            code=(midcode+endcode);
             try {
                temp = append_new_node_c(coded, find_freq(h,frequenze[q]), code);
                //std::cout<<frequenze[q]<<"\n";
            } catch(...) {
                free_nodes(coded);
                throw;
            }
            coded=temp;
            temp=0;
            delete temp;
            if(q-1<=0){
                endcode="0";
            }
            else{
                midcode=midcode+"0";
            }

    }

    h=0;
    scor=0;
    delete h;
    delete scor;
    return coded;
  }

    //trovo i T dalle frequenze
   T find_freq(node* l, const int f)
  {
    while (l != 0) {
      if (l->counter==f){
      //resetto il counter affinchè non venga ricercato in seguito
      l->counter=0;
    return l->key;}
      l = l->next;
    }
    //return 0;
  }

  const T find_freq(const node* l, const int f) const
  {
    while (l != 0) {
      if (l->counter==f){
        l->counter=0;
    return l->key;}
      l = l->next;
    }
    //return 0; //SERIO PROBLEMA AL RIGUARDO DI CIO PER LE CLASSI/COSTRUTTI che a quanto pare viene risolto restituendo un fico secco
  }

  //STAMPA DELLA CODIFICA

   node* find_code(node* l, const T& t)
  {
    while (l != 0) {
      if (cmp(l->key, t)){
      std::cout << l->codifica<<" codifica \n";
    return l;}
      l = l->next;
    }
    return 0;
  }

  const node* find_code(const node* l, const T& t) const
  {
    while (l != 0) {
      if (cmp(l->key, t)){
      std::cout << l.codifica;
    return l;}
      l = l->next;
    }
    return 0;
  }


  // Cerca k nella lista l. Restituisce il nodo corrispondente, o null
  // se la chiave non viene trovata.
  node* find_node(node* l, const T& t)
  {
    while (l != 0) {
      if (cmp(l->key, t))
    return l;
      l = l->next;
    }
    return 0;
  }

  const node* find_node(const node* l, const T& t) const
  {
    while (l != 0) {
      if (cmp(l->key, t))
    return l;
      l = l->next;
    }
    return 0;
  }

  /// Toglie n da l
  node* erase_node(node* l, node* n)
  {
    node* h = l;

    if (l == n) {
      l = l->next;
      delete n;
      return l;
    }    

    while (l != 0 && l->next != n) {
      l = l->next;
    }
    if (l == 0)
      return h;

    l->next = n->next;
    delete n;

    return h;
  }

  void free_nodes(node* l)
  {
    while (l != 0) {
      node* tmp = l;
      l = l->next;
      delete tmp;
    }
  }

  void insertion_sort(int arr[], int length) {
    int i, j ,tmp;
    for (i = 1; i < length; i++) {
        j = i;
        while (j > 0 && arr[j - 1] > arr[j]) {
            tmp = arr[j];
            arr[j] = arr[j - 1];
            arr[j - 1] = tmp;
            j--;
        }
    }
 }

public:


  class iterator
  {
  public:
    typedef T value_type;
    typedef int distance_type;
    typedef T* pointer;
    typedef T& reference;
    typedef std::forward_iterator_tag iterator_category;

    iterator() : n(0) {}

    // iterator(const iterator& it);
    // iterator& operator=(const iterator& it);

    iterator& operator++()
    {
      assert(n != 0);
      n = n->next;
      return *this;
    }

    iterator operator++(int)
    {
      iterator tmp = *this;
      operator++();
      return tmp;
    }

    reference operator*() const
    {
      assert(n != 0);
      return n->key;
    }

    pointer operator->() const
    {
      assert(n != 0);
      return &(n->key);
    }

  private:
    explicit iterator(node* nn) : n(nn) { }

    node* n;

    friend class huffman;
    friend bool operator==(const iterator& a, const iterator& b)
    {
      return a.n == b.n;
    }

    friend bool operator!=(const iterator& a, const iterator& b)
    {
      return !(a == b);
    }
  };

  class const_iterator
  {
  public:
    typedef const T value_type;
    typedef int distance_type;
    typedef const T* pointer;
    typedef const T& reference;
    typedef std::forward_iterator_tag iterator_category;

    const_iterator() : n(0) {}

    const_iterator(const iterator& it) : n (it.n) { }

    const_iterator& operator=(const iterator& it)
    {
      n = it.n;
      return *this;
    }

    const_iterator& operator++()
    {
      assert(n != 0);
      n = n->next;
      return *this;
    }

    const_iterator operator++(int)
    {
      const_iterator tmp = *this;
      operator++();
      return tmp;
    }

    reference operator*() const
    {
      assert(n != 0);
      return n->key;
    }

    pointer operator->() const
    {
      assert(n != 0);
      return &(n->key);
    }

  private:
    explicit const_iterator(node* nn) : n(nn) { }

    const node* n;

    friend class huffman;
    friend bool operator==(const const_iterator& a, const const_iterator& b)
    {
      return a.n == b.n;
    }

    friend bool operator!=(const const_iterator& a, const const_iterator& b)
    {
      return !(a == b);
    }

  };


  iterator begin() { return iterator(head); }
  iterator end() { return iterator(0); }
  const_iterator begin() const { return const_iterator(head); }
  const_iterator end() const { return const_iterator(0); }

  iterator finditer(const T& t)
  {
    return iterator(find_node(head, t));
  }

  const_iterator finditer(const T& t) const
  {
    return const_iterator(find_node(head, t));
  }
};



#endif

You are nulling a pointer before freeing it:

n = 0;
delete n;

If you pass a null pointer to delete , it will simply ignore it and the call results in a nop.

The correct sequence of operations is:

delete n; // Free referenced data
n = 0;    // Erase the reference

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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