Segfault при попытке доступа к элементу строки класса
-
28-09-2019 - |
Вопрос
У меня есть класс 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
. Отказ Я предполагаю, что это, но если я попытаюсь проверить индексы Console
MessageLog, 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!"));
}
В этом случае объект не удален после конца консоли.
Просто не забудьте удалить объекты, созданные, когда ваша программа их больше нуждается.