Деструктор класса, ошибка времени выполнения: необработанное исключение - 2 ответа

Деструктор для List работает, но возникают проблемы с деструктором для Element и List_iter:

Необработанное исключение: 0xC00000FD: переполнение стека (параметры: 0x00000001, 0x002E2F78).

Список:

#ifndef GUARD_List_h
#define GUARD_List_h

#include "Element.h"
#include "List_iter.h"


template <typename T>
class List {

public:
    List() : begins(new Element<T>), ends(new Element<T>), Element_count(0) {

        begins->t_flag = 'b';
        ends->t_flag = 'e';     

        // double link: begins & ends 
        begins->next = ends;
        ends->prev = begins;        
    }
    virtual ~List()  {
        while (begins->next != ends) {
            begins->prev = begins->next;
            begins->next = begins->next->next;
            delete begins->prev;
        }
        delete begins;
        delete ends;
    }

    typedef List_iter<T> iterator;

    iterator begin(void) const {

        iterator it(begins);
        return it;
    }
    iterator end(void) const {

        iterator it(ends);
        return it;
    }

    void push_back(const T val)  {

        Element<T>* elem = new Element<T>;      // create: new-elem         
        elem->data = val;                       // set data

        elem->prev = ends->prev;                // link: new-elem to last-data-elem
        ends->prev->next = elem;                // link: last-data-elem to new-Element                              

        elem->next = ends;                      // link: new-elem to List-end               
        ends->prev = elem;                      // link: List-end to new-elem   

        Element_count++;                        // update: when List grows      
    }
    T at(const size_t pos)  const {

        return get_Element(pos)->data;
    }
    void del(const size_t pos) const  {

        Element<T>* elem = get_Element(pos);    // get: Element for deletion        

        elem->prev->next = elem->next;          // rejoin: double link
        elem->next->prev = elem->prev;          // rejoin: double link

        delete elem;

        Element_count--;                        // update: when List shrinks

    }
    void clear(void) {

        Element<T>* ep = begins->next;
        Element<T>* ep_next = ep->next;

        while (ep->t_flag != 'e'){

            delete ep;
            ep = ep_next;
            ep_next = ep->next;
        }

        begins->next = ends;
        ends->prev = begins;

        //begins->data = 0r;
        //ends->elem_ID = 0;

        Element_count = 0;

    }

    size_t size(void) const {
        return Element_count;
    }
    bool empty(void) const {

        if (Element_count == 0){ return true; }
        else { return false; }
    }


private:
    Element<T>* begins;                           // List begins
    Element<T>* ends;                             // List ends
    size_t Element_count;                         // List size

    Element<T>* get_Element(const size_t pos) const     {

        if (empty())                        {
            std::cerr << "No Element - Empty List";
            throw;
        }
        if (pos < 0 || pos >= Element_count){
            std::cerr << "No Element - Out of Range";
            throw;
        }

        iterator it;

        // Determine the more efficent iteration direction(forward or reverse) ? 
        if ((Element_count / 2) > pos) {

            it = begin();
            for (size_t i = 0; i <= pos; i++){
                it++;
            }

        }
        else {

            it = end();
            for (size_t i = size() - pos; i > 0; i--){
                it--;
            }
        }

        return it.elem;
    }

};
#endif

Элемент:

#ifndef GUARD_Element_h
#define GUARD_Element_h

template <class T>
class List;

template <class T>
class List_iter;


template <class T>
class Element {

public:
    Element() : prev(nullptr), next(nullptr), data(), t_flag(' ') {}
    virtual ~Element()  {
        delete prev;
        delete next;        
    }
    friend List<T>;
    friend List_iter<T>;

private:
    Element<T> *prev;
    Element<T> *next;

    T data;
    int elem_ID;
    char t_flag;
};
#endif

List_iter:

#ifndef GUARD_List_iter_h
#define GUARD_List_iter_h

template <class T>
class List;


template <class T>
class List_iter {

public: 
    List_iter(Element<T>* e = nullptr) : elem(e) {}
    virtual ~List_iter()  {
        delete elem;
    }
    friend List<T>;

    T operator*(void){

        if (elem->t_flag == 'e'){

            elem = elem->prev;
        }
        else if (elem->t_flag == 'b'){

            elem = elem->next;
        }
        return elem->data;
    }

    Element<T>* operator++(void) {

        if (elem->next->t_flag == 'e'){
            return nullptr;
        }

        elem = elem->next;
        return elem;
    }
    Element<T>* operator--(void) {

        if (elem->prev->t_flag == 'b'){
            return nullptr;
        }

        elem = elem->prev;
        return elem;

    }
    List_iter operator+(const int val) {

        for (int i = 0; i < val; i++){

            this->elem = this->elem->next;
        }
        return *this;
    }
    List_iter operator-(const int val) {

        for (int i = 0; i < val; i++){

            this->elem = this->elem->prev;
        }
        return *this;
    }

    bool operator!=(const List_iter& rhs) const {

        return rhs.elem != elem;
    }
    bool operator>(const List_iter& rhs) const {

        return (this->elem->elem_ID > rhs.elem->elem_ID);
    }
    bool operator<(const List_iter& rhs) const {

        return (this->elem->elem_ID < rhs.elem->elem_ID);
    }
    bool operator>=(const List_iter& rhs) const {

        return (this->elem->elem_ID >= rhs.elem->elem_ID);
    }
    bool operator<=(const List_iter& rhs) const {

        return (this->elem->elem_ID <= rhs.elem->elem_ID);
    }


private:
    Element<T>* elem;

};
#endif

главный:

#include <iostream>
#include "List.h"


int main() {

    List<int> ls;
    List<int>::iterator begin = ls.begin();
    List<int>::iterator end = ls.end();
    List<int>::iterator iter = begin;

    std::cout << "Attempt to retrieve data from empty list: ls.at(3)" << std::endl;
    std::cout << "--------------------------------------------------" << std::endl;
    //std::cout << ls.at(3) << std::endl << std::endl;

    std::cout << "Test: growing list does not invalidate iter" << std::endl;
    std::cout << "-------------------------------------------" << std::endl;
    std::cout << "Empty list" << std::endl << std::endl;

    std::cout << "begin addr: " << &begin << " " << std::endl;
    std::cout << "end addr: " << &end << " " << std::endl;


    std::cout << std::endl << "Add data to list: 33 " << std::endl << std::endl;
    ls.push_back(33);

    std::cout << "begin addr: " << &begin << " " << std::endl;
    std::cout << "end addr: " << &end << " " << std::endl;

    std::cout << std::endl << "Add data to list: 856 " << std::endl << std::endl;
    ls.push_back(856);

    std::cout << "begin addr: " << &begin << " " << std::endl;
    std::cout << "end addr: " << &end << " " << std::endl;
    std::cout << "clear() " << std::endl << std::endl;



    ls.clear();



    std::cout << std::endl << std::endl;
    std::cout << "Add data to list: 0 1 2 3 4 5 6 7 8 9" << std::endl;
    std::cout << "-------------------------------------------------" << std::endl;
    for (int i = 0; i != 10; i++){
        ls.push_back(i);
    }


    std::cout << std::endl << std::endl;
    std::cout << "data@ begin+4" << std::endl;
    std::cout << "-------------" << std::endl;
    std::cout << *(iter + 4) << std::endl;

    std::cout << std::endl << std::endl;
    std::cout << "data@ begin->end" << std::endl;
    std::cout << "----------------" << std::endl;
    iter = begin;
    while (iter++){

        std::cout << *iter << " ";
    }


    std::cout << std::endl << std::endl << std::endl;
    std::cout << "data@ end->begin" << std::endl;
    std::cout << "----------------" << std::endl;
    iter = end;
    while (iter--){

        std::cout << *iter << " ";
    }




    std::cout << std::endl << std::endl << std::endl;
    std::cout << "for/iter: begin->end" << std::endl;
    std::cout << "----------------" << std::endl;
    for (iter = begin; iter++;){

        std::cout << *iter << " ";
    }


    std::cout << std::endl << std::endl << std::endl;
    std::cout << "iter arith: +4 +1 -1" << std::endl;
    std::cout << "--------------------" << std::endl;
    iter = ls.begin();
    iter = iter + 4;
    std::cout << *iter << " ";
    std::cout << *(iter + 1) << " ";
    std::cout << *(iter - 1) << " ";



    std::cout << std::endl << std::endl << std::endl;
    std::cout << "data@: (0)(1)(2)(3)(4)(5)(6)(7)(8)(9)" << std::endl;
    std::cout << "-------------------------------------" << std::endl;
    for (int i = 0; i != 10; i++){

        std::cout << ls.at(i) << " ";

    }



    //ls.clear();


    List<std::string> ls_str;
    ls_str.push_back("Hello");
    ls_str.push_back("World");



    return 0;    // breakpoint
}

введите описание изображения здесь


person tuk    schedule 24.04.2015    source источник
comment
Здесь целая куча кода. Предложите вам использовать отладчик, чтобы изолировать вашу проблему.   -  person Chad    schedule 24.04.2015
comment
лол, стоны, если ты не публикуешь код, стоны, если ты это делаешь. Я уже использовал отладчик, чтобы изолировать мою проблему от деструктора (вы читали OP) .. запускается во второй строке main.   -  person tuk    schedule 24.04.2015
comment
Здесь нет свидетельств переполнения стека, только нарушение прав доступа.   -  person aschepler    schedule 24.04.2015
comment
Ваш деструктор выглядит неправильно. Типичный деструктор списка выглядит так: stackoverflow.com/a/2265981/4342498.   -  person NathanOliver    schedule 24.04.2015
comment
Все ваши классы нарушают Правило трех   -  person Praetorian    schedule 24.04.2015
comment
Похоже, ~List_iter удаляет узел, принадлежащий List.   -  person aschepler    schedule 24.04.2015
comment
@ aschepler Я отредактировал, чтобы включить доказательства.   -  person tuk    schedule 24.04.2015


Ответы (1)


вызывается новый элемент, поэтому он принадлежит List, поэтому только List может удалить элемент. List_iter не требует деструктора, потому что он содержит только указатель.

person tuk    schedule 27.04.2015