Указатель на базовый класс потерян в цикле while, вызывая segfault. C++
Этот код использует цикл while для получения пользовательского ввода и выполнения соответствующей команды - для краткости я сократил его до 2 команд.
Объект Oblock создан правильно (команда "O"), как и указатель на базовый класс. Похоже, что звонки на оба объекта работают правильно. Однако после возврата в цикл while указатель на объект оказывается потерянным, а попытка доступа к его элементам (команда "t") вызывает ошибку segfault. Я включил пример кода ниже - мои вопросы потом.
#include<vector>
#include<iostream>
#include<string.h>
using namespace std;
class Tetramino {
private:
int squareSize;
vector<string> myShape;
public:
void setValues(int size) {
squareSize = size;
myShape = vector<string> ((size*size), ".");
}
string getValues(int i) {
return myShape[i];
}
int getSize() {
return squareSize;
}
};
class Oblock : public Tetramino {
public:
Oblock() {
setValues(2);
}
};
main () {
string input;
bool runProgram = true;
Tetramino *pBlock;
while (runProgram) {
cin >> input;
if (input == "O")
{
Oblock myBlock;
cerr << "0thi: " << myBlock.getValues(0) << endl;
Tetramino *pBlock = &myBlock;
cerr << "0thi: " << pBlock->getValues(0) << endl;
}
if (input == "t")
{
cerr << "0thi: " << pBlock->getValues(0) << endl;
}
}
return 0;
}
- Разрушаются ли объекты при выходе из операторов if?
- Возможно, есть лучший способ многократно получать пользовательский ввод?
Спасибо заранее за любые советы! Я искал вопросы, похожие на этот, и не мог найти подходящий для своих нужд.
4 ответа
Tetramino *pBlock
является локальным в своей области. Ты следишь за тем, кто в main
с одним внутри if
,
Также, myBlock
является локальным и будет разрушен - у вас будет свисающий указатель. Вы должны выделить new
(а также delete
...)
Вместо Tetramino *pBlock = &myBlock;
делать pBlock = new Oblock;
когда вы обрабатываете ввод "О" (и обрабатывать delete pBlock
предыдущего).
Отвечая на ваш первый вопрос: да, утверждение
Oblock yblock;
Создает экземпляр Oblock в стеке. Он уничтожается, когда код покидает соответствующий блок, поэтому любые указатели на него становятся недействительными после этого. Чтобы создать объект, который живет так долго, как вы хотите, используйте new
создать объект в куче.
if (input == "O")
{
Oblock myBlock;
cerr << "0thi: " << myBlock.getValues(0) << endl;
Tetramino *pBlock = &myBlock;
cerr << "0thi: " << pBlock->getValues(0) << endl;
}
Объект с автоматической продолжительностью хранения (обычно называемый локальной функцией-функцией) имеет время жизни, начинающееся после его объявления и заканчивающееся в конце ближайшего окружающего блока }
маркер. Так myBlock
уничтожается в конце этого оператора if и не может быть снова использован.
Также обратите внимание, что вы объявили два разных указателя с именем pBlock
, Назначение внутреннего ничего не делает с более ранним, который все еще не инициализирован.
Ваш указатель становится мусором после myBlock
выходит за рамки (где if
оператор закрывается), который будет вызывать ошибку сегментации при попытке доступа к нему позже
if(input == "O"){
Oblock myBlock;
}
^^^^ right here myBlock becomes garbage
Кроме того, если пользователь вводит "t" перед "O", это вызовет ошибку сегментации, поскольку он будет пытаться получить доступ к неинициализированному указателю. Вы, вероятно, должны это посмотреть.