2013-04-09 5 views
2

Я использовал gdb, чтобы найти точную строку с ошибкой seg. Это отмечено в функции dequeue как комментарий.Ошибка Seg при удалении временной указатель

Вот весь класс очереди.

I seg fault при вызове 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; 
} 

К сожалению, думал, что я уже отправил класс Queue:

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

Когда 'Queue :: dequeue()' вызывается, 'm_next' уже является недопустимым указателем. Или где-то где-то испорчена память. (Проблема происходит в другом месте) –

+0

Опубликовать код очереди – rerun

+0

Опубликовать ** все ** ваш код очереди и код, где вы вызываете методы очереди. – john

ответ

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

+0

Да, isEmpty() делает эту проверку. – somethingShiny

+0

@somethingShiny Теперь посмотрите, почему вы должны публиковать ** все ** свой код. Без этого мы догадываемся. – john

0

Для меня следующая строка внутри enqueue() выглядит немного странно.

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

Он создает новую очередь каждый раз.

Возможно ли вместо этого намерение быть следующим?

T * node = new T; 
0

ОК, вместо того чтобы дать вам рыбу, я научу вас, как рыба ...

Когда вы получите segmentation fault это означает, что операционная система обнаружила ошибку доступа к памяти. Обычно это происходит в C/C++, когда вы играете с указателями. указатели очень опасны и к ним нужно относиться осторожно.

Как определить, где возникла проблема? Ну, Linux не очень информативен, когда ваша программа получает SEGFAULT, однако она дает вам много информации. вам просто нужно знать, как «читать».

coredump, представляет собой изображение памяти, стека и переменных в момент возникновения ошибки сегментации. для его запуска

gdb myapp core 

, где myapp - это исполняемый файл приложения, а ядром является 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 , это покажет вам обратную трассировку из основного приложения() до фактической ошибки, включая параметры, переданные этим функциям.

Я думаю, что как только вы точно узнаете, где произошла ошибка сегментации, вам будет намного легче решить эту проблему.

Несколько замечаний:

  1. Если CoreDump не создается. типа это в консоли:

    ulimit -c unlimited 
    
  2. Вы должны скомпилировать свою программу с ключом -g, чтобы дать осмысленные имена символов в GDB.

+0

Я использовал gdb, чтобы найти точную строку с ошибкой seg. – somethingShiny

+0

Используйте bt, чтобы найти аргументы, полученные – stdcall

+0

Можете ли вы дать мне точную строку для ввода обратной трассировки? Я не уверен, что понимаю, что вы имеете в виду – somethingShiny

Смежные вопросы