Ошибка сегментации при чтении файла/ввода с помощью getline

Я пытаюсь разработать простую программу просмотра 3d-моделей, которая должна иметь возможность читать файлы построчно в формате obj. Это казалось очень простым, однако, когда std::getline достигает eof, программа завершается с ошибкой сегментации.

Здесь я сделал наименьшее количество кода, который дает мне segfault (здесь я использую std::cin, так что моя программа не завершается сразу, но у меня действительно есть возможность ввести в нее кое-что и вручную ввести eof ):

std::string line;
while(std::getline(std::cin, line))
    {
        std::cout<<line;
    }

Еще одна вещь, на которую следует обратить внимание, это то, что этот код вызовет segfault только в том случае, если строка, содержащая eof, пуста, в противном случае, если eof вводится в строке, содержащей что-либо еще, цикл просто продолжается.

Изменить: теперь я воспроизвел это с наименьшим возможным кодом:

main.cpp

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

int main(int argc, char* argv[])
{

    std::string path = "/home/thor/Skrivebord/3d_files/Exported.obj";
    obj::Model(path.c_str());

    return 0;
}

Model.h

#ifndef MODEL_H_INCLUDED
#define MODEL_H_INCLUDED

namespace obj
{
    class Model
    {
    public:
        Model(const char* path);
    };
}

#endif // MODEL_H_INCLUDED

Model.cpp

#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <string>

namespace obj
{
    class Model
    {
    public:
        Model(const char* path);

    private:
        std::string name = ""; // Remove this line, and all works.
    };

    Model::Model(const char* path)
    {
        std::string line;

        while(std::getline(std::cin, line))
        {
            std::cout << line;
        }
    }
}

person Community    schedule 24.11.2013    source источник
comment
Просто сделайте while (getline(cin, line)) без условного eof().   -  person 0x499602D2    schedule 24.11.2013
comment
Я уже пробовал это, и это все еще дает мне segfault.   -  person    schedule 24.11.2013
comment
Затем покажите нам свой фактический код.   -  person 0x499602D2    schedule 24.11.2013
comment
В размещенных двух строках кода нет ничего плохого. Какой бы ни была ваша проблема, она в коде, который вы не опубликовали.   -  person john    schedule 24.11.2013
comment
Есть золотая середина между публикацией почти никакого кода и публикацией всего вашего кода. Начните удалять вещи из своего кода, делайте программу все меньше и меньше, но все еще с ошибкой, о которой вы спрашиваете. Когда программа настолько мала, насколько вы можете ее сделать, но все еще имеет ошибку, опубликуйте весь этот код.   -  person john    schedule 24.11.2013
comment
Что-то здесь серьезно не так. Я не могу проверить ваш точный код, потому что у меня нет С++ 11. Но это ни в коем случае не должно рухнуть, как вы говорите. Какой компилятор вы используете?   -  person john    schedule 24.11.2013
comment
Я использую gcc 4.8 на Ubuntu 12.04. И я не вижу ни одной части кода, использующего C++11.   -  person    schedule 24.11.2013
comment
std::string name = "" разрешено только в C++11. Я тестировал его без = "", и у меня он не вылетал (неудивительно).   -  person john    schedule 24.11.2013
comment
Теперь я протестировал его и без = "", и он все равно выдает segfault.   -  person    schedule 24.11.2013
comment
@ Lillesort131 Хорошо, теперь я вижу, я был слеп. Я отвечу через минуту.   -  person john    schedule 24.11.2013


Ответы (2)


Проблема в том, что в вашем коде есть два конфликтующих объявления Model.

В Model.cpp у вас есть

class Model
{
public:
    Model(const char* path);

private:
    std::string name = ""; // Remove this line, and all works.
};

но в Model.h у вас есть

class Model
{
public:
    Model(const char* path);
};

У вас должно быть только одно определение Model, поместите его в Model.h и #include "Model.h" в Model.cpp.

person john    schedule 24.11.2013
comment
Какие именно части кода мне нужно переместить? Если я просто перемещу сам класс, Model::Model(const char* path){ ... } выдаст мне ошибку. - person ; 24.11.2013
comment
Просто переместите сам класс и добавьте #include "Model.h" в Model.cpp. - person john; 24.11.2013
comment
У вас должно быть только одно определение любого класса. Поместите это определение в заголовочный файл и #include заголовочный файл в любом месте, где вам это нужно. Это метод, позволяющий убедиться, что у вас есть непротиворечивые определения классов в вашем коде. - person john; 24.11.2013
comment
Спасибо, теперь это работает. Я просто забыл #include "Model.h. - person ; 24.11.2013

Это выглядит как ошибка, хотя логику трудно проследить.

void Face::AddVertex(float x, float y, float z)
{
    if (vCnt > 3)
    {
        vertices[vCnt].SetPos(x, y, z);
        ++vCnt;
    }
    else
    {
        vertices.push_back(Vertex(x, y, z));
        ++vCnt;
    }
}

Это более логично с <, а не >, поскольку ваш вектор vertices изначально имеет размер 3.

void Face::AddVertex(float x, float y, float z)
{
    if (vCnt < 3)
    {
        vertices[vCnt].SetPos(x, y, z);
        ++vCnt;
    }
    else
    {
        vertices.push_back(Vertex(x, y, z));
        ++vCnt;
    }
}
person john    schedule 24.11.2013