"return new node"内存泄漏,我找不到修复它的方法

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

本文关键字:方法 找不到 new return node 内存 泄漏      更新时间:2023-10-16

有一个函数返回一个"新节点"的问题,我找不到它。下面是函数:

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报告:

==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$ 

我现在将复制其他类命名为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;}

另一项功能
huffman(const huffman& v)
: head(0), sz(0), cmp(v.cmp){
head = build_list(v.begin(), v.end(), sz);}
真的,伙计们,如果有人能帮我,那就太棒了。我真的找不到我必须释放或删除,以防止这种内存泄漏。我没有复制所有的代码,因为大约300行,但如果你需要它,我会的。

int main(){ 
try {
do_test();
dotest_iterators();
std::cout << "okn";} 
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);}

我希望你们能帮助我

更新:我将把所有的代码放在这里:

#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

在释放指针之前将指针清空:

n = 0;
delete n;

如果你传递一个空指针给delete,它将简单地忽略它,调用结果为nop。

正确的操作顺序是:
delete n; // Free referenced data
n = 0;    // Erase the reference