列表实现中的分段错误(核心转储)[C ++]

时间:2015-05-15 21:25:09

标签: c++ list implementation core fault

我知道这对我的第一个问题来说是一个漫长的问题,但我确实试图在2周内解决这个问题而无济于事。

我很确定我的问题是与记忆相关的问题,即使我已经搜索了其他人的解决方案,我也没有运气。

以下是代码:

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>

using namespace std;

typedef string tElemLista;

typedef struct nodo {
    tElemLista title;
    tElemLista info; // el elemento en sí
    nodo *next; // puntero autoreferencial
    nodo *prev;
    // al proximo nodo
} tNodo;

class tLista {
    tNodo *head;
    tNodo *tail;
    tNodo *curr;
    unsigned int listSize;
    unsigned int pos; // posición actual en la lista
public:
    tLista() {
        head = tail = curr = NULL;
        listSize = 0; // lista vacía
        pos = 0;
    }
    void Clear(){
        tNodo * temp;
        moveToStart();
        while (listSize!=0){
            temp = curr;
            moveToNext();
            free(temp);
            listSize--;
        }

        head = tail = curr = (tNodo *)malloc(sizeof(tNodo));
        listSize = 0; // lista vacía
        pos = 0;

    }
    int Insert(){
        tNodo * temp;

        if (listSize == 0){
            head = tail = curr = (tNodo *)malloc(sizeof(tNodo));
            curr->next = curr->prev = NULL;
            listSize++;
        }
        else if (curr == tail){
            curr->next = (tNodo *)malloc(sizeof(tNodo));
            curr->next->prev = curr;
            if (curr == tail){
                tail = curr->next;
            }
            listSize++;
        }
        else{
            temp = curr->next;
            curr->next = (tNodo *)malloc(sizeof(tNodo));
            curr->next->prev = curr;
            curr->next->next = temp;
            temp->prev = curr->next;
            listSize++;
        }
        return pos;
    }
    int append(tElemLista item){
        unsigned int temp = pos;
        moveToEnd();
        Insert();
        moveToPos(temp);
        return pos;
    }
    tElemLista Remove(){
        tNodo * borrar;
        tElemLista retorno = curr->info;
        if (listSize == 1){
            free(curr);
            head = tail = curr = NULL;
            listSize = 0;
        }
        else if(curr == head){
            borrar = curr;
            head = head->next;
            if (head == NULL){
                tail = NULL;
            }
            else{
                curr = head;
                head->prev = NULL;
            }
            listSize--;
            free(borrar);
        }
        else if(curr == tail){
            borrar = curr;
            tail = tail->prev;
            if (tail == NULL){
                head = NULL;
            }
            else{
                curr = tail;
                tail->next = NULL;
            }
            listSize--;
            pos--;
            free(borrar);
        }
        else{
            borrar = curr;
            curr->prev->next = curr->next;
            curr->next->prev = curr->prev;
            listSize--;
            free(borrar);
        }
        return retorno;
    }

    void moveToStart(){
        curr = head;
        pos = 0;
    }
    void moveToEnd(){
        curr = tail;
        pos = listSize;
    }
    void moveToNext(){
        if (curr != tail){
            //cout<< "\n\n" << curr->next<< "\n\n\n";
            curr = curr->next;
            pos++;
        }
    }
    void moveToPrev() {
        if (curr != head){
            curr = curr->prev;
            pos--;
        }
    }

    int length(){
        return listSize;
    }
    int currPos(){
        return pos;
    }
    void moveToPos(unsigned int to){
        while (to != pos){
            if (to > pos){
                moveToNext();
            }
            else{
                moveToPrev();
            }
        }
    }
    tElemLista getValue(){
        return curr->info;
    }
    tElemLista setValue(tElemLista input){
        tElemLista antiguo;
        //cout << input <<"\n";
        curr->info = input;
        return antiguo;
    }
    tElemLista getTitle(){
        return curr->title;
    }
    tElemLista setTitle(tElemLista input){

        tElemLista antiguo;

        //cout << curr->title <<"\n";
        //cout << input <<"\n";
        //cout << "OO";
        curr->title = input;
        //cout << curr->title <<"\n";
        return antiguo;
    }

};


int main(){
    string linea_input; //El profesor Arroyuelo nos dijo que podíamos usar string de STL.
    string comando;
    string info;
    string opened_output;

    tLista Presentacion;

    fstream archivo_input("input.txt");
    fstream archivo_output;

    if (!archivo_input.is_open()){
        perror("Error al abrir input.txt");
        return 1;
    }

    while(!archivo_input.eof()){
        getline(archivo_input, linea_input);

        size_t found;
        if ((found = linea_input.find(" ")) != string::npos){
            comando = linea_input.substr(0,found);
            info = linea_input.substr(found+1, string::npos);

            if (comando == "NUEVA_PRESENTACION"){
                info.append(".txt");
                Presentacion.Insert();
                //cout << info;
                opened_output = info;
                archivo_output.open(opened_output.c_str()); //Crear archivo
            }
            else if (comando == "CARGAR_PRESENTACION"){

            }

            else if (comando == "SET_CONTENIDO"){

                Presentacion.setValue(info);
            }
            else if (comando == "SET_TITULO"){
                //cout << "HM";
                Presentacion.setTitle(info);
            }




        }
        else{
            if (linea_input == "NUEVA_DIAPOSITIVA"){

                Presentacion.Insert();
                //cout << "UNOVA\n";
            }
            else if (linea_input == "VER_DIAPOSITIVA"){
                cout << "Posicion: " << Presentacion.currPos();
                cout << " - Titulo: " << Presentacion.getTitle();
                cout << " - Contenido: " << Presentacion.getValue() << "\n";
            }
            else if (linea_input == "SIGUIENTE"){
                Presentacion.moveToNext();
            }
            else if (linea_input == "ANTERIOR"){
                Presentacion.moveToPrev();
            }
            else if (linea_input == "ELIMINAR_DIAPOSITIVA"){
                Presentacion.Remove();
            }
            else if (linea_input == "GUARDAR"){
                unsigned int temp_pos = Presentacion.currPos();
                Presentacion.moveToStart();
                archivo_output << "DIAPOSITIVA #" << Presentacion.currPos() << "\n";

                archivo_output << Presentacion.getTitle() << "\n";
                archivo_output << Presentacion.getValue() << "\n";

                while(Presentacion.currPos() != Presentacion.length()- 1){

                    Presentacion.moveToNext();
                    archivo_output << "DIAPOSITIVA #" << Presentacion.currPos() << "\n";
                    archivo_output << Presentacion.getTitle() << "\n";
                    archivo_output << Presentacion.getValue() << "\n";
                    archivo_input.close();
                    archivo_input.open(opened_output.c_str());
                }
                Presentacion.moveToPos(temp_pos);
            }
            else if (linea_input == "SALIR"){
                Presentacion.Clear();
                return 0;
            }
        }
        /*
        if(linea_input.npos != pos_corte) {
            comando = comando.substr(pos_corte + 1);
            linea_input = linea_input.substr(0, pos_corte);
        }
        */
        //cout << linea_input << "\n";
        //cout << comando << "\n";


        //cout << comando << "\n";
    }

    archivo_input.close();
    return 0;
}

任何帮助?

修改 这是input.txt文件:

NUEVA_PRESENTACION TAAA
SET_TITULO titulo 1
SET_CONTENIDO blah blah blah
SET_CONTENIDO blah
VER_DIAPOSITIVA
GUARDAR
SALIR

1 个答案:

答案 0 :(得分:5)

首先,在使用各种文件I / O和其他不重要的事情之前,你应该编写一个非常小的测试程序。

我拿了你的代码,并创建了以下3行main程序(我使用的是Visual C ++ 2013):

int main()
{
    tLista myList;
    myList.append("abc");
    myList.append("123");  // < -- hangs here
}

这是你应该开始和测试的。

这就是我需要用你的代码复制一个主要问题。问题出在这里:

    head = tail = curr = (tNodo *)malloc(sizeof(tNodo));

无法使用malloc来创建tNodo对象。该类包含std::string成员,这意味着它不是POD类型。

您无法使用malloc实例化非POD类型(除非您以后使用placement-new)。您必须使用new动态创建对象。

    head = tail = curr = new tNodo();

您在代码的其他部分中犯了同样的错误。

这只是一个明显的错误。你可能有其他人,所以我建议你现在废弃你的main程序并像上面那样编写简单的测试。

有关POD类型的更多信息:What are POD types in C++?