#c #segmentation-fault #polymorphism #virtual-functions
#c #ошибка сегментации #полиморфизм #виртуальные функции
Вопрос:
Я пытаюсь создать FSM для простого компилятора.
Я решил создать массив фиксированного размера с интерфейсными указателями на состояния. Эта концепция оказалась успешной с простым заполнителем FSM, который читает HTML.
Однако реальный FSM не будет работать: я получаю ошибку сегментации (при 0x0) при вызове метода обработки состояний.
Вот создание экземпляра:
this->states[0] = new State0();
this->states[1] = new State1();
this->states[2] = new State2();
this->states[3] = new State3();
this->states[4] = new State4();
[...]
Когда я прохожу через это, я вижу, что соответствующий адрес меняется после каждого назначения.
Массив определяется таким образом:
#define STATE_COUNT 17
[...]
IState * states[STATE_COUNT];
IState:
class IState {
public:
virtual ~IState() {};
virtual int getNextState(char) = 0;
virtual bool isFinal() = 0;
virtual TokenType getTokenType() = 0;
};
State0, с минимизированным кодом для целей тестирования:
class State0 : public IState
{
public:
virtual ~State0();
int getNextState(char c)
{
return 0;
}
bool isFinal()
{
return this->final;
}
TokenType getTokenType()
{
return this->tokenType;
}
private:
TokenType tokenType;
bool final;
};
Теперь следующая строка кода вызывает ошибку SEGFAULT:
this->nextState = this->states[currentState]->getNextState(c);
currentState
равно 0, поскольку это происходит при самом первом вызове.
Итак, я думаю, что это не проблема области видимости и не нулевой указатель. За исключением, возможно, нулевого значения этого указателя в объектах состояния?
Комментарии:
1. Вы действительно уверены
currentState
0
, что это так? Вы распечатали его перед вызовом?2. Я прошел, так что да. Но тем временем я определил проблему — я забыл переключить включенный заголовок при переключении объектных файлов. D:
3. К сожалению, очень распространенная ошибка, даже среди опытных программистов, я могу вас заверить!
4. Дэниел, добро пожаловать в Stack Overflow. Если вопрос может представлять ценность для других, пожалуйста, отправьте ответ в разделе ответов. Публикация ответа в теле вопроса — ужасная практика, она приведет к тому, что вы проголосуете против. Если это никому не нужно, удалите его. Но будьте осторожны… слишком много удалений, и вы будете забанены.
Ответ №1:
Как упоминалось в комментариях, эта проблема возникла из-за моей собственной небрежности. Я отредактировал свой Makefile для создания других объектов, но не смог изменить заголовки на новые в моем коде. Поэтому я связал («внешне» похожие) новые объектные файлы с другим кодом, все еще используя старые заголовки.