Почему доступ к этой локальной переменной-члену вызывает исключение?

0

Я пытаюсь написать программу, которая будет считывать содержимое CSV файла в массив, а затем выводить результаты на экран (часть более крупного проекта), когда функция getNumberOfRooms() вызывается исключением, когда она пытается возвращает значение переменной numberOfRooms, частный член внутри класса. У кого-нибудь была такая проблема раньше или кто-то помог с такой проблемой? Если да, то как вы его решили?

Заранее спасибо,

Полный исходный код доступен здесь: https://bitbucket.org/skutov/micropuzzle/

Исключение, которое вызывается при вызове getNumberOfRooms():

Unhandled exception at 0x01354aa6 in MICROPUZZLE.exe: 0xC0000005: Access violation
reading location 0xccccccd0.

Это функции, о которых идет речь (все время, на которые ссылается переменная в классе)

ClassMap::ClassMap ()
{
    numberOfRooms = 0;

    // Get number of rooms in map.csv

    /* Find number of entries in map.csv file */

        numberOfRooms = number_of_lines;

    // allocate memory for rooms array

    /* loading data from file into array */
    }
}    

// self explanitory
int ClassMap::getNumberOfRooms()
{
    // Exception occurs on this line when accessing the variable
    return numberOfRooms;
}

int ClassMap::printRoomDescriptions ()
{
    for(int j = this->getNumberOfRooms(); j > 0; j--)
    {
        cout << roomArray[j].getDescription();
    }
    return 0;
}

Вот заголовок класса:

class ClassMap
{
private:
    int currentLocation;
    int numberOfRooms;
    // pointer to array initialised in constructor
    ClassRoom *roomArray;

public:
    // Constructors and Destructors
    ClassMap();
    ~ClassMap();

    // Print description, events and directions for current room
    std::string getCurrentRoom();

    // Change currentLocation to neighbour of current room if possible
    int moveRoom(char direction);


    // self explanitory
    int getNumberOfRooms();

    // dump room descriptions to command line (debugging)
    int printRoomDescriptions();

};

Вот конструктор ClassMap, который также инициализирует roomArray:

ClassMap::ClassMap ()
{
    numberOfRooms = 0;

    // Get number of rooms in map.csv

        unsigned int number_of_lines = 0;
        FILE *infile = fopen("map.csv", "r");
        int ch;

        while (EOF != (ch=getc(infile)))
            if ('\n' == ch)
                ++number_of_lines;
        fclose(infile);
        numberOfRooms = number_of_lines;




    // allocate memory for rooms array
    roomArray = new ClassRoom[numberOfRooms+1];

    // set starting room
    int currentLocation = 1;

    // load that shit up
    {
        // Holders for values read from file
        int newRoomID = 0;
        char newRoomDescription[79] = "";
        int newRoomNorthNeighbour = 0;
        int newRoomEastNeighbour = 0;
        int newRoomSouthNeighbour = 0;
        int newRoomWestNeighbour = 0;

        // used for iterations
        int i = 0;

        // File stream for map.csv
        std::ifstream mapFile;

        // Crack that shit open
        mapFile.open ("map.csv");

        // Line buffer for parsing
        std::string line;


        // For each line in the map.csv file read in the values into variables declared above then run initialise function for each room to store values into array
        while (std::getline(mapFile, line))
        {
            // re-init parameters

            newRoomID = 0;
            newRoomNorthNeighbour = 0;
            newRoomEastNeighbour = 0;
            newRoomSouthNeighbour = 0;
            newRoomWestNeighbour = 0;
            for(i = 0;i<79;i++)
            {
                newRoomDescription[i] = ' ';
            }


            int parameter = 0;

            int paraStart = 0;
            int paraEnd = 0;

            std::string buffer;
            std::istringstream iss(line);

            for(parameter = 0; parameter <= 5; parameter++)
            {
                // Empty buffer from last iteration
                buffer.clear();

                // Find end of current parameter
                paraEnd = line.find(',',paraStart+1);

                switch (parameter)
                {
                case 0:
                    buffer = line.substr((paraStart),(paraEnd-paraStart));
                    newRoomID = atoi(buffer.c_str());
                    break;
                case 1:
                    buffer = line.substr((paraStart+2),(line.find("\"",paraStart+2)-(paraStart+2)));
                    for(i = 0;i<(buffer.length());i++)
                    {
                        newRoomDescription[i] = buffer.c_str()[i];
                    }
                    //newRoomDescription
                    break;
                case 2:
                    buffer = line.substr((paraStart+1),(paraEnd-paraStart));
                    newRoomNorthNeighbour = atoi(buffer.c_str());
                    break;
                case 3:
                    buffer = line.substr((paraStart+1),(paraEnd-paraStart));
                    newRoomEastNeighbour = atoi(buffer.c_str());
                    break;
                case 4:
                    buffer = line.substr((paraStart+1),(paraEnd-paraStart));
                    newRoomSouthNeighbour = atoi(buffer.c_str());
                    break;
                case 5:
                    buffer = line.substr((paraStart+1),(paraEnd-paraStart));
                    newRoomWestNeighbour = atoi(buffer.c_str());
                    break;
                } // switch

                // Cycle paraEnd to paraStart
                paraStart = paraEnd;

            } // for parameters loop

            // Init next room with data
            new (&roomArray[newRoomID]) ClassRoom(  newRoomNorthNeighbour,
                newRoomEastNeighbour,
                newRoomSouthNeighbour,
                newRoomWestNeighbour,
                newRoomDescription);

        } // while !EOF
        // Close the file because we're a good little program and we don't need that shit no more
        mapFile.close();
    }
}
  • 2
    Вероятно, потому что указатель this недействителен. Пожалуйста, покажите код, где вы вызываете getNumberOfRooms() . Проблема скорее всего там.
  • 0
    как вы инициализируете roomArray? не могли бы вы показать свой конструктор?
Показать ещё 1 комментарий
Теги:
exception
members

2 ответа

2

Ключом к этой проблеме является:

Access violation reading location 0xccccccd0

0xcccccccc - специальное значение, используемое в режиме отладки для обозначения униализированного указателя. (См. Раздел Как заключить указатель на 0xCCCCCCCC). Он установлен в режиме отладки, чтобы вызвать такой крах - это означает, что указатель, который вы используете, еще не настроен. После правильной настройки указателя ошибка исчезнет. (Небольшое отличие от 0xcccccccc - смещение члена, к которому вы пытаетесь получить доступ внутри этого объекта.)

ДОБАВЛЕНО:

Это ваша ошибка:

ClassRoom* roomArray = static_cast<ClassRoom*>( ::operator new ( sizeof ClassRoom * numberOfRooms ) );

Это создает локальную переменную roomArray и скрывает переменную-член. Вы действительно хотите:

roomArray = static_cast<ClassRoom*>( ::operator new ( sizeof ClassRoom * numberOfRooms ) );

Или еще лучше:

roomArray = new ClassRoom[numberOfRooms];
  • 0
    Спасибо за совет, принимая во внимание ваши изменения, это не имеет значения для программы, за исключением того, что она выглядит немного аккуратнее. Я отредактировал изменения в исходном вопросе. Просто чтобы убедиться, что все понятно, переменная <code> numberOfRooms </ code> в этом контексте прекрасно используется, именно функция get вызывает ошибку.
  • 0
    Код выглядит лучше, но он все еще изобилует странностями и потенциальными ошибками. (Не могу сказать, являются ли они действительными ошибками, так как у нас нет всего кода.) Я думаю, вам действительно нужно создать уменьшенный пример кода, чтобы показать нам, если вам нужна дополнительная помощь. Смотрите sscce.org для того, что ожидается.
1

Я предполагаю, что проблема заключается в том, что ваш цикл for(int j = this->getNumberOfRooms(); j > 0; j--). Он должен выглядеть так: for(int j = this->getNumberOfRooms()-1; j >= 0; j--). Последний доступный индекс в arry с N элементами - N -1. С другой стороны, первый индекс равен 0.

  • 0
    Спасибо за указатель, не совсем там, где проблема, но это выдвинуло на первый план проблему с тем, как я написал свои файлы .csv. Сохранена потенциальная головная боль там.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню