Указатель на базовый класс потерян в цикле while, вызывая segfault. Переполнение стека

Этот код использует цикл 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?
  • Возможно, есть лучший способ многократно получать пользовательский ввод?

Спасибо заранее за любые советы! Я искал вопросы, похожие на этот, и не мог найти подходящий для своих нужд.

1

Решение

Tetramino *pBlock является локальным в своей области. Ты следишь за тем, кто в main с одним внутри if,

Также, myBlock является локальным и будет разрушен — у вас будет свисающий указатель. Вы должны выделить new (а также delete…)

Вместо Tetramino *pBlock = &myBlock; делать pBlock = new Oblock; когда вы обрабатываете ввод «О» (и обрабатывать delete pBlock предыдущего).

3

Другие решения

 if (input == "O")
{
Oblock myBlock;
cerr << "0thi: " << myBlock.getValues(0) << endl;
Tetramino *pBlock = &myBlock;
cerr << "0thi: " << pBlock->getValues(0) << endl;
}

Объект с автоматической продолжительностью хранения (обычно называемый локальной функцией-функцией) имеет время жизни, начинающееся после его объявления и заканчивающееся в конце ближайшего окружающего блока } маркер. Так myBlock уничтожается в конце этого оператора if и не может быть снова использован.

Также обратите внимание, что вы объявили два разных указателя с именем pBlock, Назначение внутреннего ничего не делает с более ранним, который все еще не инициализирован.

1

Отвечая на ваш первый вопрос: да, утверждение

Oblock yblock;

Создает экземпляр Oblock в стеке. Он уничтожается, когда код покидает соответствующий блок, поэтому любые указатели на него становятся недействительными после этого. Чтобы создать объект, который живет так долго, как вы хотите, используйте new создать объект в куче.

1

Ваш указатель становится мусором после myBlock выходит за рамки (где if оператор закрывается), который будет вызывать ошибку сегментации при попытке доступа к нему позже

if(input == "O"){
Oblock myBlock;
}
^^^^ right here myBlock becomes garbage

Кроме того, если пользователь вводит «t» перед «O», это вызовет ошибку сегментации, поскольку он будет пытаться получить доступ к неинициализированному указателю. Вы, вероятно, должны это посмотреть.

0
По вопросам рекламы [email protected]