2014-08-29 111 views
0

我正在嘗試編寫一個簡單版本的標準容器std :: list,作爲C++練習。然而,由於我是C++新手,並且來自python/java,所以我在內存管理方面面臨困難,我們不必擔心這些。代碼如下:調試「malloc錯誤:指針被釋放未被分配」,使用gdb

#include <memory> 
#include <cstddef> 
#include <iostream> 

template <typename T> class List { 
    public: 
     typedef std::size_t size_type; 
     typedef T value_type; 
     typedef T& reference; 
     typedef const T& const_reference; 

     template <typename U> class Node { 
      public: 
       Node() { 
        data = NULL; 
        init(); 
       } 
       Node(const U val) { 
        data = new U(val); 
        init(); 
       } 

       void init() { 
        prev = NULL; 
        next = NULL; 
       } 

       ~Node() { 
        if (data != NULL) 
         delete data; 
        if (prev != NULL) 
         delete prev; 
        if (next != NULL) 
         delete next; 
       } 

       U* data; 
       Node* prev; 
       Node* next; 
     }; 


     class iterator { 
      public: 
       iterator() { 
        n = new Node<T>(); 
       } 
       iterator(const T val) { 
        n = new Node<T>(val); 
       } 
       iterator(Node<T>* nodeptr) { 
        n = nodeptr; 
       } 
       ~iterator() { 
        delete n; 
       }  

       iterator operator++() { 
        n = n->next; 
       } 
       iterator operator--() { 
        n = n->prev; 
       } 
       T& operator*() { 
        return *(n->data); 
       } 
       bool operator==(iterator other) { 
        return (this->n == other.n); 
       } 
       Node<T>* n; 
     }; 

     List() { 
      _begin = new iterator(); 
      _end = new iterator(begin.n); 
     } 

     List(size_type n, T val) { 
      init(val); 
     } 

     ~List() { 
      delete _begin; 
      delete _end; 
     } 

     void init(T val) { 
      _begin = new iterator(val); 
      Node<T>* nextNode = new Node<T>(); 
      _begin->n->next = nextNode; 
      nextNode->prev = _begin->n; 
      _end = new iterator(nextNode); 
     } 

     void push_back(T val) { 
      if(_begin == _end) { 
       delete _begin; 
       delete _end; 
       init(val); 
      } 
      else { 
       Node<T>* endNode = _end->n; 
       Node<T>* lastNode = endNode->prev; 
       Node<T>* append = new Node<T>(val); 
       lastNode->next = append; 
       append->next = endNode; 
       append->prev = lastNode; 
       endNode->prev = append; 
      } 
     } 

     iterator begin() {return *_begin;} 
     iterator end() {return *_end;} 
    private: 
     iterator* _begin; 
     iterator* _end; 
}; 

int main() { 
    List<int> derp= List<int>(3,3); 
    List<int>::iterator i = derp.begin(); 
    std::cout << *i; 
    derp.push_back(4); 
    std::cout << *i; 
} 

當我運行代碼,我得到以下輸出:

a.out(814) malloc: *** error for object 0x7fbab0403a70: pointer being freed was not allocated 
*** set a breakpoint in malloc_error_break to debug 
33Abort trap: 6 

我用GNU調試器設置斷點按計劃,並得到了以下結果:

(gdb) break malloc_error_break 
Function "malloc_error_break" not defined. 
Make breakpoint pending on future shared library load? (y or [n]) y 
Breakpoint 1 (malloc_error_break) pending. 
(gdb) run 
Starting program: /Users/samadwara/Projects/C++/a.out 
Reading symbols for shared libraries ++.............................. done 
Breakpoint 1 at 0x7fff90721588 
Pending breakpoint 1 - "malloc_error_break" resolved 
a.out(835) malloc: *** error for object 0x100103a90: pointer being freed was not allocated 
*** set a breakpoint in malloc_error_break to debug 

Breakpoint 1, 0x00007fff90721588 in malloc_error_break() 
(gdb) backtrace 
#0 0x00007fff90721588 in malloc_error_break() 
#1 0x00007fff90722942 in free() 
#2 0x0000000100001864 in List<int>::Node<int>::~Node (this=0x100103a70) at list2.cpp:30 
#3 0x0000000100001894 in List<int>::Node<int>::~Node (this=0x100103ad0) at list2.cpp:32 
#4 0x00000001000018d0 in List<int>::Node<int>::~Node (this=0x100103a70) at list2.cpp:34 
#5 0x000000010000190f in List<int>::iterator::~iterator (this=0x7fff5fbff930) at list2.cpp:55 
#6 0x00000001000012ae in main() at list2.cpp:117 
(gdb) frame 2 
#2 0x0000000100001864 in List<int>::Node<int>::~Node (this=0x100103a70) at list2.cpp:30 
warning: Source file is more recent than executable. 
30       delete data; 
(gdb) l 
25      next = NULL; 
26     } 
27 
28     ~Node() { 
29      if (data != NULL) 
30       delete data; 
31      if (prev != NULL) 
32       delete prev; 
33      if (next != NULL) 
34       delete next; 

我看到的問題是與刪除數據,但據我瞭解的數據總是與新初始化的,所以我沒有看到這個問題。任何建議,即使在代碼的其他方面,都表示讚賞。

+0

'delete NULL'是一個無操作的BTW,並使用'nullptr'。另外,你還沒有調試你的最新源代碼。最後,節點的析構函數也不應該釋放其兄弟節點。當它們被破壞時會發生什麼? – 2014-08-29 01:49:33

+0

'我試圖寫一個標準容器std :: list的簡約版本,作爲一個C++練習'這就像一個初學者鋼琴學生說的「我試圖演奏這個貝多芬的鋼琴協奏曲的極簡版」。 – PaulMcKenzie 2014-08-29 03:47:05

回答

2

問題就在這裏:

  ~Node() { 
       if (data != NULL) 
        delete data; 
       if (prev != NULL) 
        delete prev; 
       if (next != NULL) 
        delete next; 
      } 

當你刪除第一點,它試圖通過delete next;

但是,刪除第2節點,在~Node()對於第二點,它會嘗試刪除第一個節點再次delete prev;

正確的方法是刪除data~Node();遍歷列表來刪除每個節點,而不是通過prevnext刪除。

+0

好的,這是有道理的,但你會如何修改〜迭代器方法,以便我不會在不同的位置做出完全相同的錯誤? – Nezo 2014-08-29 02:05:04

+0

我建議不要在'iterator()'和'〜iterator()'中分配或釋放'Node'。讓'List'的成員函數做到這一點。 – timrau 2014-08-29 02:07:31

+0

如果是這種情況,那麼刪除一個迭代器意味着什麼,就像我在push_back中做的那樣?我以爲迭代器應該刪除節點,因爲它攜帶指向節點的指針? – Nezo 2014-08-29 02:10:50

相關問題