Segfault при попытке доступа к элементу строки класса

StackOverflow https://stackoverflow.com/questions/3088581

Вопрос

У меня есть класс Message что имеет а std::string В качестве члена данных определен следующим образом:

class Message
{
// Member Variables
    private:
        std::string text;
        (...)

// Member Functions
    public:
        Message(const std::string& t)
        : text(t) {}

        std::string getText() const {return text;}
        (...)
};

Этот класс используется в векторе в другом классе, как это:

class Console
{
// Member Variables
    private:
        std::vector<Message> messageLog;
        (...)

// Member Functions
    public:
        Console()
        {
            messageLog.push_back(Message("Hello World!"));
        }

        void draw() const;
};

В draw(), есть итератор, который звонит getText(). Отказ Когда это делает, программа SegFaults. Я решил это text действительно внутри Message конструктор. Тем не менее, я не могу сказать, если это действительно изнутри Console. Отказ Я предполагаю, что это, но если я попытаюсь проверить индексы ConsoleMessageLog, GDB говорит мне это:

(gdb) p messageLog[0]
One of the arguments you tried to pass to operator[] could not be converted to what the function wants.

Кто-нибудь знает, что происходит?

Редактировать: вот draw(). TCODConsole является частью библиотеки проклятий, которые я использую, и поэтому эта функция печатает каждое сообщение в Console к части экрана Curses. TL и BR находятся Point объекты участника (два INT), которые говорят, где на экране рисовать Console. Отказ Я оставил части Message и Console В оригинальном вопросе, чтобы надеяться сделать вещи более четкими, но если вам нужно, чтобы я позволил поступить все классы, то я могу. Они не слишком длинные.

void Console::draw() const
        {
            int x = TL.getX(), y = TL.getY();
            int width = BR.getX() - TL.getX();
            int height = BR.getY() - TL.getY();

            // draw the Console frame
            TCODConsole::root->printFrame(x, y, width, height, true);

            // print the Console's messages
            vector<Message>::const_iterator it;
            for(it=messageLog.begin(); it<messageLog.begin()+height-1; ++it)
            {
                string message = "%c" + it->getText();
                TCODConsole::setColorControl(TCOD_COLCTRL_1, 
                                             it->getForeColor(),
                                             it->getBackColor());
                y += TCODConsole::root->printRectEx(x, y, width, height,
                                                    TCOD_BKGND_NONE,
                                                    TCOD_LEFT,
                                                    message.c_str(),
                                                    TCOD_COLCTRL_1);
            }
        }
Это было полезно?

Решение

Я думаю, что по точке, которую вы используете it->getText(), Итератор нулевой. Добавьте чек it != messageLog.end() Когда вы идете по массиву, а до звонка it->getText().

Другие советы

Это определенно std::vector messageLog и нет std::vector<Message> messageLog? Это кажется немного странным.

Какое отношение высота имеет к индексу вектора? У тебя есть:

messageLog.begin()+height-1;

Почему вы добавляете координату экрана к итератору? Это, кажется, ваша проблема, и вы, скорее всего, чрезмерно перенесены, и поэтому вы получаете SIGSEGV.

То, что вы, вероятно, хотите, это просто повторить все сообщения в векторе и отображать их в определенном месте на экране. Я вижу, что вы пытаетесь сделать, но если вы пытаетесь рассчитать границу экрана, используя итератор, вы определенно собираетесь не так. Попробуйте запустить счетчик или получить messageLog.size() а затем пересчитывать высоту каждой итерацией. Что касается петли, просто делай:

for(it=messageLog.begin(); it!=messageLog.end(); ++it)

Это, вероятно, потому что сфера Message объект, созданный в Console метод - это только Console метод. Итак, если ваша программа пытается получить доступ к этому объекту в другом методе, как draw, вы получите эту ошибку сегментации, поскольку этот объект удаляется после выполнения.

Попробуйте это (просто вставьте new ключевое слово):

    Console()
    {
        messageLog.push_back(new Message("Hello World!"));
    }

В этом случае объект не удален после конца консоли.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top