2013-04-09 39 views
2

我使用gdb查找seg故障的確切行。它在離隊功能中被註釋爲評論。刪除臨時指針時發生Seg錯誤

這是整個隊列類。

如果有兩個對象和隊列中的發送者,則在調用dequeue()時發生故障。

template <typename T> 
void Queue<T>::clear() 
{ 
    while(!isEmpty()) 
     dequeue(); 
} 

template <typename T> 
void Queue<T>::enqueue(const T& x) 
{ 

    if(isEmpty()) 
    { 
     Queue<T>* temp = new Queue<T>; 
     m_data = x; 
     m_next = temp; 
     return; 

    } 


    Queue<T>* temp = this; 

    while(temp->m_next != NULL) 
    { 
     temp = temp->m_next; 
    } 
    Queue<T>* node = new Queue<T>(); 
    temp->m_data = x; 
    node->m_next = temp->m_next; 
    temp->m_next = node; 
    return; 
} 

template <typename T> 
void Queue<T>::dequeue() 
{ 
    if(isEmpty()) 
     return; 
    if(m_next != NULL) 
    { 
     Queue<T>* temp = m_next; 
     m_data = temp->m_data; 
     m_next = temp->m_next; 
     delete temp; //Seg fault here 
    } 
    return; 
} 

template <typename T> 
const T& Queue<T>::front() const throw (int) 
{ 
    if(isEmpty()) 
     throw 0; 
    return m_data; 
} 

template <typename T> 
bool Queue<T>::isEmpty() const 
{ 
    return (m_next==NULL); 
} 

template <typename T> 
int Queue<T>::size() const 
{ 
    int size = 0; 
    const Queue<T>* temp = this; 
    while(temp->m_next != NULL) 
    { 
     temp = temp->m_next; 
     size++; 
    } 
    return size; 
} 

對不起,以爲我已經張貼隊列類:

template <typename T> 
class Queue : public AbstractQueue<T> { 
public: 
    Queue(){m_next = NULL;}; 

    virtual void clear(); 

    virtual void enqueue(const T& x); 

    virtual void dequeue(); 

    virtual const T& front() const throw (int); 

    virtual bool isEmpty() const; 

    virtual int size() const; 

    ~Queue(){ 
     clear(); 
     return; 
    }; 
private: 
    T m_data; 
    Queue* m_next; 
}; 

而且從這個類繼承:

template < typename T > 
class AbstractQueue 
{ 
public: 

    // Purpose: clears the queue 
    // Postconditions: the queue is now empty 
    // -- PURE VIRTUAL 
    virtual void clear() = 0; 

    // Purpose: enqueue an element into the queue 
    // Parameters: x is the item to add to the queue 
    // Postconditions: x is now the element at the end of the queue, 
    // -- PURE VIRTUAL 
    virtual void enqueue(const T& x) = 0; 

    // Purpose: dequeues 
    // Postconditions: the element formerly at the front of the queue has 
    //  been removed 
    // Dequeueing from an empty Queue produces no errors, queue remains empty. 
    // -- PURE VIRTUAL 
    virtual void dequeue() = 0; 

    // Purpose: looks at the front of the queue 
    // Returns: a reference to the element currently in front of the queue 
    // Exception: if the queue is currently empty, throw SOMETHING!! 
    // -- PURE VIRTUAL 
    virtual const T& front() const = 0; 

    // Purpose: Checks if a queue is empty 
    // Returns: 'true' if the queue is empty 
    //  'false' otherwise 
    // -- PURE VIRTUAL 
    virtual bool isEmpty() const = 0; 

    // Purpose: Returns the size of a queue. 
    // Returns: the number of elements in the Queue 
    // -- PURE VIRTUAL 
    virtual int size() const = 0; 

    // ---------------- 

    // Purpose: Destructor 
    // -- VIRTUAL 
    virtual ~AbstractQueue() {}; 

}; 
+0

當'隊列 ::出隊()'被調用時,'m_next'已經是一個無效的指針。或者內存在某處被損壞。 (問題在其他地方發生) – 2013-04-09 20:39:39

+0

發佈您的排隊代碼 – rerun 2013-04-09 20:40:41

+0

發佈**所有**您的排隊代碼以及您調用Queue方法的代碼。 – john 2013-04-09 20:46:28

回答

0

在此代碼:

Queue<T>* temp = m_next; 
m_data = m_next->m_data; 
m_next = m_next->m_next; 

你不檢查m_next是否爲非null(如果你're在列表的末尾),所以你開始解引用空指針,所有的賭注都在這個時候關閉。

+0

我會想象'isEmpty()'會檢查。但該代碼尚未公佈。 – john 2013-04-09 20:45:21

+0

是的,isEmpty()會檢查。 – somethingShiny 2013-04-09 20:46:54

+0

@somethingShiny現在看看爲什麼你應該發佈**所有**你的代碼。沒有它,我們猜測。 – john 2013-04-09 20:47:33

0

對我來說,enqueue()裏面的下面一行看起來有點奇怪。

Queue<T>* node = new Queue<T>(); 

它每次都創建一個新的隊列。

是否可以改爲以下意圖?

T * node = new T; 
0

OK,而不是給你一條魚,我會教你如何釣魚...

當你segmentation fault這意味着該操作系統已檢測到一個內存訪問錯誤。 當你玩指針時,這通常發生在C/C++中。指針非常危險,必須小心處理。

如何檢測出現問題的位置? 那麼,當您的程序收到SEGFAULT時,Linux並不是非常豐富,但是它提供了大量信息。你只需要知道如何「閱讀」它。

coredump,是在出現分段錯誤時的內存,堆棧和變量的圖片。運行它

gdb myapp core 

其中myapp是您的應用程序可執行文件,而core是coredump。 現在你會看到類似這樣的:

GNU gdb 19991004 

Copyright 1998 Free Software ���.� 

Core was generated by `testit'. 

Program terminated with signal 11, Segmentation fault. 

Reading symbols from /usr/lib/libstdc++-libc6.1-1.so.2...done. 

Reading symbols from /lib/libm.so.6...done. 

Reading symbols from /lib/libc.so.6...done. 

Reading symbols from /lib/ld-linux.so.2...done. 

#0 0x823221a in main() at blabla.c:3 

10    *i++;  

它會準確地告訴你哪一行引起的故障。 如果您想確切知道如何到達該行,請鍵入bt 這將向您顯示從應用程序main()直到實際故障(包括傳遞給函數的參數)的回溯。

我認爲,一旦你確切地知道分段錯誤發生的位置,你將更容易解決它。

幾點注意事項:

  1. 如果不創建轉儲。在控制檯 類型的:

    ulimit -c unlimited 
    
  2. 你需要使用-g編譯程序,以使在gdb的符號有意義的名稱。

+0

我用gdb找到seg錯誤的確切行。 – somethingShiny 2013-04-09 20:57:20

+0

使用bt來查找傳遞的參數 – stdcall 2013-04-09 20:58:09

+0

你能給我一個確切的行來輸入回溯嗎?我不確定我完全理解你的意思 – somethingShiny 2013-04-09 21:12:13