Указатель на базовый класс потерян в цикле 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", это вызовет ошибку сегментации, поскольку он будет пытаться получить доступ к неинициализированному указателю. Вы, вероятно, должны это посмотреть.

Другие вопросы по тегам