Нарушение доступа к месту записи динамически размещаемого массива - PullRequest
0 голосов
/ 23 апреля 2020

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

Exception thrown at 0x50D540C9 (vcruntime140d.dll) in Glicko2.exe: 0xC0000005: Access violation writing location 0xC39903E3.

Из исследования этой топи c кажется, что это исключение в основном появляется, если вы пытаетесь выполнить запись вне вашего массива. Однако внутри для l oop, где я пишу это, должно быть невозможно писать вне этого. Исключение происходит в строке

         posResponsesTeamNames[i] = teamName;   

, и мой код

int league::matchSet()
{
    std::string currLine;
    std::string *posResponsesTeamNames = new std::string[league::numTeams];
    std::string posResponsesWon[3] = { "1","2","3" };
    team* team1;
    team* team2;
    bool successful = false;
    for (int i = 0; i < league::numTeams; i++) {
         std::string teamName = league::getName(i + 1);
         for (i = 0; i < teamName.size(); i++) {
             teamName.at(i) = toupper(teamName.at(i));
         }
         posResponsesTeamNames[i] = teamName;   
    }
    std::cout << posResponsesTeamNames[1];
roundStart:
    for (int i = 0; i < league::numMatches; i++) {
        std::cout << "for match " << i + 1 << " please enter name of first team to play: ";
        std::getline(std::cin, currLine);
        int parsed = parseText(currLine, posResponsesTeamNames);
        if (parsed == 2) {
            delete[] posResponsesTeamNames;
            prepForEnd();
            return 2;
        }
        else if (parsed == 0) {
            goto roundStart;
        }
        for (int i = 0; i < league::teams.size(); i++) {
            if (currLine == league::teams.at(i).getName()) {
                successful = true;
                team1 = &league::teams.at(i);
            }
        }
        if (successful == false) {
            std::cout << "ERROR: Invalid team name entered";
            goto roundStart;
        }
secondTeam:
        std::cout << "for match " << i + 1 << " please enter name of second team to play: ";
        std::getline(std::cin, currLine);
        parsed = parseText(currLine, posResponsesTeamNames);
        if (parsed == 2) {
            delete[] posResponsesTeamNames;
            prepForEnd();
            return 2;
        }
        else if (parsed == 0) {
            goto secondTeam;
        }
        for (int i = 0; i < league::teams.size(); i++) {
            if (currLine == league::teams.at(i).getName()) {
                successful = true;
                team2 = &league::teams.at(i);
            }
        }
        if (successful == false) {
            std::cout << "ERROR: Invalid team name entered";
            goto secondTeam;
        }
whoWon:
        std::cout << "please enter 1 if the first team won, 2 if the second team won or 3 if it was a draw: ";
        std::getline(std::cin, currLine);
        parsed = parseText(currLine, posResponsesWon);
        if (parsed == 2) {
            delete[] posResponsesTeamNames;
            prepForEnd();
            return 2;
        }
        if (parsed == 0) goto whoWon;
    }
    delete[] posResponsesTeamNames;
}

Ответы [ 2 ]

1 голос
/ 23 апреля 2020
1    std::string currLine;
2    std::string *posResponsesTeamNames = new std::string[league::numTeams];
3    std::string posResponsesWon[3] = { "1","2","3" };
4    team* team1;
5    team* team2;
6    bool successful = false;
7    for (int i = 0; i < league::numTeams; i++) {
8         std::string teamName = league::getName(i + 1);
9         for (i = 0; i < teamName.size(); i++) {
10             teamName.at(i) = toupper(teamName.at(i));
11        }
12       posResponsesTeamNames[i] = teamName;   
13    }

Предположение : значение league :: numTeams равно 10

в строке № 2 вы создаете массив размером 10 (league :: numTeams).

в строке 7, создал счетчик локальной переменной i .

в строке 8, создав локальную переменную teamName

в строке 9 присваивает 0 i (создан в строке 7) и начинает al oop. Вы увеличиваете это в этом l oop. размер teamName может быть больше 10 ( league :: numTeams ). Предположим, 12.

Таким образом, значение i может быть больше 10 (league :: numTeams). Теперь в строке 12 вы присваиваете значение в posResponsesTeamNames в позиции i , которая сейчас равна 12 . Это назначение точно не выполнится.

Возможное решение : в строке 9 вместо i используйте int j в качестве второго счетчика на локальная переменная teamName

Я надеюсь, что это даст вам ответ.

0 голосов
/ 23 апреля 2020

Когда вы вызываете ключевое слово 'new', это вызывает ваш конструктор вашего класса. Если ваш constrictor создает экземпляр только что выделенного объекта для null, а затем, когда в вашем l oop вы отменяете ссылку на этот объект, он имеет тенденцию создавать нарушения доступа. Если ваш констриктор инициализирует ваши объекты таким образом, который позволяет немедленную разыменование (инициализация пустой строкой «»), что может позволить вам писать в этот «новый» объект без нарушения прав доступа.

...