Получение странного возвращаемого значения из char * в переполнении стека

Я новичок в программировании на С ++ и получаю странное значение, возвращаемое из переменной char *, которую я установил, в зависимости от того, как я ее использую. Я, очевидно, делаю что-то действительно глупое, но я не вижу проблемы. Следующие пара абзацев описывают настройку (плохо), но, вероятно, проще просто взглянуть на вывод и код.

В принципе, у меня есть пара классов — Menu и MenuItem. Класс MenuItem имеет имя типа char *. В зависимости от того, как я использую пункты меню, я получаю странные результаты, когда я выполняю getName () для MenuItems.

У меня есть класс Machine, который имеет состояние (TestState). Этот TestState создает меню, содержащее элементы MenuItem. Когда я создаю TestState в моей основной функции и заставляю его распечатать меню, я получаю то, что ожидаю. Когда я создаю Машину, которая содержит TestState, и прошу его напечатать меню, она печатает что-то странное для имени корневого элемента в меню.

Выход — Последняя строка, которую я ожидаю menuItem1, но я получаю HâΔHã = ò

Output direct from TestState Object

Displaying menu state
menuItem1
root not null
menuItem1Output from TestState within Machine

Displaying menu state
menuItem1
root not null
Hâ∆Hã=ò

Вот мой код —
main.cpp

#include "Menu.h"#include "Machine.h"#include <iostream>

using namespace std;

Machine m;
TestState t;

int main(void) {
cout << "Output direct from TestState Object" << endl << endl;
t = TestState();
t.print();cout << endl << endl << "Output from TestState within Machine" << endl << endl;
m = Machine();
m.printCurrentState();
}

Menu.h

#ifndef Menu_h
#define Menu_h

#include <stdlib.h>

class MenuItem {
public:
MenuItem();
MenuItem(const char* itemName);
const char* getName() const ;

protected:
MenuItem *next;
const char* name;
};

class Menu {
public:
Menu(MenuItem *rootItem);
Menu();
void setRoot(MenuItem *r);
MenuItem* getRoot() ;
protected:
MenuItem *root;
};

#endif

Machine.h

#ifndef MACHINE_H_
#define MACHINE_H_

#include "Menu.h"
class TestState;
class Machine;

class TestState {
public:
TestState();
virtual ~TestState();
void print();
protected:
Machine* machine;
MenuItem menuItem1;
Menu menuMain;
};

class Machine {
public:
Machine();
void printCurrentState();
protected:
TestState testState;
};

#endif /* MACHINE_H_ */

Machine.cpp

#include "Machine.h"#include <iostream>
using namespace std;

TestState::TestState() {
menuItem1 = MenuItem("menuItem1");
menuMain = Menu(&menuItem1);
}

void TestState::print(){
cout << "Displaying menu state " << endl;
cout << menuItem1.getName() << endl;

if (menuMain.getRoot() == NULL) {
cout << "root is null" << endl;
} else {
cout << "root not null " << endl;
cout << menuMain.getRoot()->getName() << endl;
}
}

TestState::~TestState() {
// TODO Auto-generated destructor stub
}

Machine::Machine() {
testState = TestState();
}

void Machine::printCurrentState() {
testState.print();
}

Любая помощь будет оценена. Я немного растерялся.
Спасибо
Дейв

0

Решение

Я подозреваю, что происходит Menu.root указывает на временный объект где-то. Вы заметите, что вы делаете копию своей машины в своей основной функции:

// in main():
m = Machine(); // makes a machine, then copies it

Эта машина имеет TestState, который имеет MainMenu, который имеет указатель на MenuItem:

// in MenuItem class definition:
MenuItem *root;

Этот указатель инициализируется по адресу члена вашей первоначальной машины. Проблема в том, что этот объект существует только в течение короткого времени: он уничтожается после завершения копирования, оставляя вас с висящим указателем.

Другими словами, вам нужно убедиться, что при копировании объекта, содержащего указатели, вы обновите эти указатели, чтобы они отражали адрес дублированного объекта вместо старого.

Вам нужно добавить конструкторы копирования, как показано ниже:

Machine::Machine(const Machine& other)
{
teststate = other.teststate;
teststate.machine = this; // you will need to expose TestState.machine to Machine
}

TestState::TestState(const TestState& other)
{
machine = other.machine; // Machine copy constructor modifies this for us

menuItem1 = other.menuItem1; // these 3 we have to do
menuItem2 = other.menuItem2;
menuMain = other.menuMain;

menuMain.setRoot(&menuItem1); // update pointers to be to persistent copies
menuItem1.setNext(&menuItem2);
menuItem2.setNext(NULL);
}

Вы можете заметить, что ваша система довольно хрупкая. Я бы порекомендовал меньше полагаться на указатели между объектами, потому что драконы идут по этой дороге.

4

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

TestState::TestState() {
menuItem1 = MenuItem("menuItem1");
menuItem2 = MenuItem("menuItem2");
menuMain = Menu(&menuItem1);
menuMain.add(&menuItem2);
}

Machine::Machine() {
testState = TestState();
}

Machine конструктор создает временный TestState и копирует свои данные членов в Machine::testState, Когда Machine конструктор сделан, временный TestState исчезает, но Machine::testState.menuMain.root по-прежнему указывает на члена временного.

Как исправить:

Узнайте, что подразумевается под каждым из различных способов инициализации переменных, и как использовать списки инициализации в ваших конструкторах.

1

Вместо того чтобы писать Thing name = Thing(ctorParams); сделать имя указателя и использовать new Thing(ctorParams);, Похоже, вы думали, что используете указатели, но это работало без нового ключевого слова, поэтому вы пошли дальше и не использовали их, что вызывало ошибки.

1

Machine не имеет конструктора копирования, поэтому различные указатели и ссылки внутри Machine (в частности, в TestState) указывают на мусор.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector