String subscript out of range c ошибка

Подобные ошибки означают, что во время работы программы была предпринята попытка обращения к памяти, не подготовленной должным образом для этого. Программа с такими ошибками содержит неопределённое поведение. Самыми говорящими из рассмотренных в вопросе ошибок являются те, где сказано «subscript out of range». Дословно это переводится как «Индексация вне диапазона». Понятность их обеспечивается в первую очередь тем, что программа собрана в отладочном (Debug) режиме и соответствующий код индексации operator[] того или иного контейнера (std::array, std::string, std::vector) непосредственно содержит проверку значения индекса, передаваемого в оператор индексации. Например, так выглядит код в msvc 2019 для std::array:

    _NODISCARD _CONSTEXPR17 reference operator[](_In_range_(0, _Size - 1) size_type _Pos) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
        _STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0

        return _Elems[_Pos];
    }

Другие сообщения не так очевидны, потому что возникают при работе приложений, собранных без отладочной информации и/или оптимизированных так, что подробное отладочное сообщение не содержится/не связано с выполняемый кодом, но причины их возникновения часто те же самые.

Решение проблемы прямо вытекает из текста отладочных сообщений — индекс, по которому идёт обращение к элементу контейнера, должен быть в допустимом диапазоне. Т.е. если контейнер имеет размер N, допустимыми индексами будут являться 0...N-1. Исключением из этого правила является std::string, где допускается так же использовать индекс N, но с оговоркой, что писать туда можно только нулевой символ , и он же вернётся при чтении.

Довольно часто проблема выхода за допустимые границы диапазона случается в циклах, когда условие завершение содержит нестрогое сравнение индекса с размером контейнера: т.е. i <= size вместо i < size. В подобных случаях итерации по элементам, следует по возможности пользоваться диапазонной версией цикла for, которая не допускает выхода за пределы контейнера, если размер контейнера остаётся постоянным в процессе итерирования.

std::vector<int> v = {1, 2, 3};
for(int i = 0; i <= v.size(); ++i) // ошибка. <= вместо <
   v[i] = 42;                      // проблема на последней итерации

for(auto& e : v)                   // диапазонный for 
   e = 42;                         // e всегда принадлежит вектору

Иногда цикл кажется правильным, но вместо v.size() по незнанию указывают v.max_size(), который говорит вообще о потенциально возможном размере контейнера для данной архитектуры, а не о текущем размере. Понятно, что в этом случае можно выйти далеко за пределы разрешённых величин.

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

for(int i = 0; i < v.size(); ++i) {
   v[f(i)] = ...   // f(i) может возвращать другой диапазон
   v[i - 1] = ...  // использование "предыдущего" индекса. Ошибка для i == 0.
}

Другой возможный случай — когда возникает путаница между ассоциативными контейнерами (где operator[] приводит к созданию/добавлению элемента в контейнер, если его ещё не было) и последовательными контейнерами. Например:

std::map<int, int> m;
m[0] = 42; // ok, добавляется элемент с ключом 0 и ему присваивается значение 42

std::vector<int> v;
v[0] = 42; // ошибка, вектор пустой, элемента с индексом 0 не существует

Добавить элемент в вектор можно либо при инициализации std::vector<int> v = {42};, либо позднее, например, через v.push_back(42).

Иногда ошибка может возникать, когда вместо std::vector::resize был вызван std::vector::reserve. Т.е. память выделена и доступ идёт только к элементам внутри выделенной памяти, но логически размер вектора не был изменён (элементы вектора фактически не проинициализированы). При Release сборке в этом случае может вовсе не возникнуть ошибки доступа (access violation), но такая программа не будет считаться валидной.

Чтобы обеспечить дополнительную проверку диапазона используемых индексов как в отладочном, так и в релизном режимах сборки вместо operator[] можно воспользоваться функцией at(), которая выбросит исключение std::out_of_range при использовании индекса вне разрешённого диапазона. В некоторых случаях сложного вычисления индекса это может быть оправдано, но внесёт дополнительный оверхед.

Маринчик

0 / 0 / 3

Регистрация: 12.10.2012

Сообщений: 150

1

02.03.2017, 22:24. Показов 3070. Ответов 9

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Разбираю пример, который дала препод в примерах к лекциям..Пример по коду Виженера.. Пару раз запустился-результат выводился.Исправила только алфавит на кириллицу,и поставила на некоторые строки коменты.Теперь консолька запускается, начальный этап проходит, но потом результат не выводится, и консолька просто виснет..и выбивает это сообщение про «Debug assertion failed : string subscript out of range»

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// 11.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <string>
#include <iostream>
#include <conio.h>
 
using namespace std;
 
int main()
{
    string TEXT, KEY, D = "";
    string A = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ-_,."; //наш алфавит
    setlocale(LC_ALL, "Rus");
    cout << "Введите предложение: ";
    cin >> TEXT;
    KEY =  "МАРИНА";
    int *F = new int[TEXT.size()];
    int *G = new int[TEXT.size()];
    int key = KEY.size(); //делаем замену переменных для удобства
    int text = TEXT.size();
    
    if (text >= key)//Первое условие. Если длина вводимого слова больше, либо равна длине ключа
    {
        for (int i = 0; i < (text / key); i++)
        {
            D = D + KEY; //Записываем целое количество ключа. Растягивая ключ по длине слова.
        }
        for (int j = 0; j < (text%key); j++)
        {
            D = D + KEY[j];
        }
    }
    else  //Иначе если ключ длиннее слова, укорачиваем ключ до длины слова.
    {
        for (int s = 0; s < text; s++)
        {
            D = D + TEXT[s];
        }
    }
 
//cout<<"Распишем ключ под текст: ";
//cout << D << endl;
 
    for (int k = 0; k < text; k++)//Здесь мы уже начинаем шифровать.
    {
        for (int n = 0; n < 36; n++)
        {
            if (TEXT[k] == A[n])// Смысл заключается втом, что мы ищем номер буквы во вводимом ключе и номере, 
            {
                F[k] = n;
            }
 
            if (D[k] == A[n])
            {
                G[k] = n;
            } ///И после чего записываем их в массив
 
        }
    }
 
    int e = 0; //Для суммы номеров символов. Чтобы при достижении 36 буквы или символа, программа шла по кругу, начиная с первого номера
bool shifr;
cout<<"для шифрования введите 1, для расшифровки нажмите 0: ";
cin>>shifr;
if (shifr==1){
    for (int u = 0; u < text; u++)
    {
        e = ((F[u] + G[u]) % 36);
        TEXT[u] = A[e];
    }
 }
else
    for (int u = 0; u < text; u++)
    {
        e = ((F[u] - G[u]));
        if (e<0)
            e+=36;
        TEXT[u] = A[e];
    }
    cout << "Зашифрованное слово: " << TEXT << endl;
 
    
    _getch();
    return 0;
 
}

По пошаговой отладке понимаю что проблема вроде как с загрузкой символов на 81 строчке.. А как сделать чтоб работало нормально-правильно?



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

02.03.2017, 22:24

9

284 / 232 / 114

Регистрация: 07.09.2016

Сообщений: 584

02.03.2017, 22:34

2

в вашей 81 строке ничего такого, что может родить ассерт не происходит.
поведение вашей программы зависит от того, что вы там вводите. я вбил что-то от балды и ассертов не было.
в таких случаях вводные данные надо писать тут, а еще лушче тупо хардкодить, вместо того, чтобы запрашивать
у пользователя их ввод. сильно экономит время всем. после отладки хардкод можно убирать.
ну и до кучи почитайте третий пост из темы:
Как пользоваться отладчиком (в Visual Studio)



0



Lambont

93 / 91 / 62

Регистрация: 23.11.2013

Сообщений: 242

02.03.2017, 22:48

3

Особо не вникал в код, но, пройдя отладчиком, у вас после 69 строки

C++
1
        e = ((F[u] + G[u]) % 36);

переменная e в любом случае будет содержать очень большое число, которое потом используется как индекс символа в строке, а размер строки явно меньше чем это число, вот и ошибка выхода за границы string.



0



nd2

3434 / 2813 / 1249

Регистрация: 29.01.2016

Сообщений: 9,426

02.03.2017, 22:54

4

Цитата
Сообщение от Маринчик
Посмотреть сообщение

По пошаговой отладке понимаю

Найди точное место в коде, где ошибка вылетает. Судя по ошибке, где-то выходишь за границу string, значит внимание к местам, где к string A по индексу обращаешься. Например:

C++
1
2
3
4
        e = ((F[u] - G[u]));
        if (e<0)
            e+=36;
        TEXT[u] = A[e];



0



1272 / 1029 / 470

Регистрация: 25.12.2016

Сообщений: 3,333

02.03.2017, 22:55

5

Цитата
Сообщение от Lambont
Посмотреть сообщение

переменная e в любом случае будет содержать очень большое число

От нуля до 35 — вроде не очень большое. А в массиве А как раз 36 элементов.
Точнее, 37 элементов, так что делить по модулю нужно на 37, если я правильно понял алгоритм.



0



3434 / 2813 / 1249

Регистрация: 29.01.2016

Сообщений: 9,426

02.03.2017, 22:57

6

Цитата
Сообщение от Lambont
Посмотреть сообщение

еременная e в любом случае будет содержать очень большое число

Тут, как раз, не будет. Здесь от 0 до 35.

Добавлено через 55 секунд

Цитата
Сообщение от likehood
Посмотреть сообщение

А в массиве А как раз 36 элементов.

37.



0



93 / 91 / 62

Регистрация: 23.11.2013

Сообщений: 242

02.03.2017, 23:05

7

Цитата
Сообщение от likehood
Посмотреть сообщение

От нуля до 35 — вроде не очень большое. А в массиве А как раз 36 элементов.

Цитата
Сообщение от nd2
Посмотреть сообщение

Тут, как раз, не будет. Здесь от 0 до 35.

Странно, у меня явно переменная е после 69 строки всегда отрицательное значение имеет, чтобы я не вводил, и именно здесь мне бросает исключение выхода за границы



0



3434 / 2813 / 1249

Регистрация: 29.01.2016

Сообщений: 9,426

02.03.2017, 23:13

8

Цитата
Сообщение от Lambont
Посмотреть сообщение

е после 69 строки всегда отрицательное значение имеет,

Отрицательный индекс — это тоже выход за границу.



0



likehood

1272 / 1029 / 470

Регистрация: 25.12.2016

Сообщений: 3,333

02.03.2017, 23:17

9

Кажется понял в чём дело. Если строка содержит только символы алфавита, то программа не вылетает. Но если есть хотя бы один пробел или например цифра, то 51 строка не будет выполнена и этот элемент массива не будет инициализирован. Отсюда и все глюки.

Кроме того, для корректного ввода русских букв нужно в начале программы добавить строки

C++
1
2
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);

Ну и естественно, шифруемый текст должен содержать только большие буквы.


Я бы вообще сначала отладил программу для английского алфавита, а потом при желании добавил поддержку русского.



1



Lambont

93 / 91 / 62

Регистрация: 23.11.2013

Сообщений: 242

02.03.2017, 23:18

10

Цитата
Сообщение от nd2
Посмотреть сообщение

Отрицательный индекс — это тоже выход за границу.

Вот вот, я и о том же. Я даже больше скажу, у меня и после 76 строки

C++
1
        e = ((F[u] - G[u]));

в е космические числа, видимо в массивах F и/или G что-то не-то происходит… дойду до дома — подробнее посмотрю тогда



0



КОД:

#include <iostream>
#include <string>

using namespace std;

string codeNormalization(string code) {
	string result;
	for (int i = 0; i < code.size(); i++) {
		if (code[i] == 'n') {
			result += "\n";
		}
		else if (code[i] == '"') {
			result += ''';
		}
		else if (code[i] == 't') {
			result += "\t";
		}
		else {
			result += code[i];
		}
	}
	return result = R"("exec(''')" + result + "''')" + R"(")";
}

string myOBF(string codeLine) {
	string result;
	for (int i = 0; i < codeLine.capacity(); i++) {
		int _ord = (int)codeLine[i];
		if (codeLine[i] == codeLine[-1]) {
			result += "chr(" + to_string(_ord) + "))";
		}else if (codeLine[i] == codeLine[0]){
			result += "exec(chr(" + to_string(_ord) + ")+";
		}else {
			result += "chr(" + to_string(_ord) + ")+";
		}
	}
	return result;
}

int main() {
	string code = "print('txt')";
	cout <<myOBF(codeNormalization(code)) << endl;
	system("pause");
}

Ошибка появляется в MessageBox после появления консоли.
Сама ошибка:
string subscript out of range
При дебаге кидает в xstring
Ошибка появилась сразу после написания функции myOBF. <ОШИБКА ГДЕ ТО В НЕЙ>
Ошибка пропадает если из цикла for убрать все if и else if :(

Hello, I am working on a project and I have run into a slight error. I am setting up an array to spit out the ICAO words for a given string. (Ex. Input = «GO» — Output = «Golf Oscar») It compiles cleanly the first time, but after I get the output, I get the error «String Subscript Out of Range». What does this mean and how can I fix it? Thank you very much. I couldn’t find any information online that I could understand, frankly, so I hope you guys can help me.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <string>
using namespace std;


int main()
{               
	string stringin;
	int index = 0;
	string ICAO[26] = { "Alpha" , "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", 
						"Hotel", "India", "Juliet", "Kilo", "Lima", "Mike", "November", 
						"Oscar", "Papa", "Quebec", "Romeo", "Sierra", "Tango", "Uniform"
						"Victor", "Whiskey", "X-ray", "Yankee", "Zulu" } ;

	do
	{		
	cout << "Please enter string or press 9 to exit:   " << endl;			
	cout << endl;
	cin >> stringin;
	cout << endl;
	cout << "The phonetic version is:   " << endl;
	cout << endl;
	
	for (int i=0; stringin.size(); i++)	
	{
		string stringout;
		char letter;
		letter = toupper(stringin[i]);
		stringout = ICAO[letter-'A'];
		cout << stringout << " ";

	}

	cin.get();
	cin.get();

	} while (stringin != "9");

	return 0;
}

моя часть кода делает проверку на путь ,который указывают для файла. В этом пути должны быть исключены все зарезервированные имена Windows ( из серии con,clock$ и т.п. ) , в целом я был уверен, что написал правильную функцию, но после запуска стало выдавать ошибку «string subscript out of range» . Подскажите , пожалуйста, в чём моя ошибка.

bool CheckFile(string path) {
        int retry = 0, numbers, point = 0, miniNameSize = 0, numberPoints;
        int sizePath = size(path);
                    for (numberPoints = sizePath; numberPoints >= 0; numberPoints--) {
                    if (path[numberPoints] == '.') {
                    point = numberPoints;
                    break;
                    }
                    for (int k = 0; k < sizePath; k++) {
                    if (path[k] == '.' && k != point ) {
                    path.erase(k, 1);
                    k--;
                    }
                    sizePath = size(path);
                    }
                    for (int k = 0; k < sizePath; k++) {
                    if (path[k] == ' ') {
                    path.erase(k, 1);
                    k--;
                    }
                    }
                    sizePath = size(path);
            for (numbers = 0; numbers < sizePath; ) {
            if ((path[numbers] == '\' || path[numbers] == '/') || numbers == 0) {
                for (int n = 1; (path[numbers + n] != '\' || path[numbers + n] != '/' || path[numbers + n] != '.'); n++) miniNameSize = n;
                // Работаем с именем 
                if (miniNameSize == 0) numbers++;
                else {
                    if (numbers == 0) numbers--;
                    for (int j = numbers + 1 ; j <= miniNameSize; ) {                                           // Аккуратно с j !!!!
                        if (miniNameSize - j < 3) break;
                        else {
                            if (j + 3 == miniNameSize + 1) {
                                if ((path[j] == 'n' || path[j] == 'N') && (path[j + 1] == 'u' || path[j + 1] == 'U') && (path[j + 2] == 'l' || path[j + 2] == 'L')) retry++;
                                if ((path[j] == 'c' || path[j] == 'C') && (path[j + 1] == 'o' || path[j + 1] == 'O') && (path[j + 2] == 'n' || path[j + 2] == 'N')) retry++;
                                if ((path[j] == 'p' || path[j] == 'P') && (path[j + 1] == 'r' || path[j + 1] == 'R') && (path[j + 2] == 'n' || path[j + 2] == 'N')) retry++;
                                if ((path[j] == 'a' || path[j] == 'A') && (path[j + 1] == 'u' || path[j + 1] == 'U') && (path[j + 2] == 'x' || path[j + 2] == 'X')) retry++;
                            }
                            if (j + 4 == miniNameSize + 1) {
                                if ((path[j] == 'c' || path[j] == 'C') && (path[j + 1] == 'o' || path[j + 1] == 'O') && (path[j + 2] == 'm' || path[j + 2] == 'M') && (path[j+ 3] == '1' || path[j + 3] == '2' || path[j + 3] == '3' || path[j + 3] == '4')) retry++;
                                if ((path[j] == 'l' || path[j] == 'L') && (path[j + 1] == 'p' || path[j + 1] == 'P') && (path[j + 2] == 't' || path[j + 2] == 'T') && (path[j + 3] == '1' || path[j + 3] == '2' || path[j + 3] == '3')) retry++;
                            }
                            if (j + 6 == miniNameSize + 1) {
                                if ((path[j] == 'c' || path[j] == 'C') && (path[j + 1] == 'l' || path[j + 1] == 'L') && (path[j+ 2] == 'o' || path[j + 2] == 'O') && (path[j + 3] == 'c' || path[j + 3] == 'C') && (path[j + 4] == 'k' || path[j + 4] == 'K') && path[j + 5] == '$') retry++;
    
                            }
                        }
                        }
                    
                    }
                numbers = numbers + (miniNameSize + 1);
                miniNameSize = 0;
                    
                }
            }
        }

Понравилась статья? Поделить с друзьями:
  • String memory leak after effects ошибка
  • String indices must be integers python ошибка
  • String data ui splash lua ошибка teardown
  • Stress web 13 ошибка mysql
  • Stress cache aida64 ошибка