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, но с оговоркой, что писать туда можно только нулевой символ \0, и он же вернётся при чтении.

Довольно часто проблема выхода за допустимые границы диапазона случается в циклах, когда условие завершение содержит нестрогое сравнение индекса с размером контейнера: т.е. 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. Показов 3414. Ответов 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



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;
}

КОД:

#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 :(

I’m starting to use strings in place of character arrays and am encountering an error when I change one of my character arrays defined with a size of 5 to a string. The error I get is «Expression: string subscript out of range» upon trying to run the program.

«newWord» was originally a character array, but upon changing it to a string I’m getting this error. I don’t understand what could be causing this, when using the character array the program performs fine.

int main() {
fstream inputFile;
fstream outputFile;
string newWord;
int i, k;
string word;
inputFile.open( "H:\\word.txt" );
outputFile.open( "H:\\newword.txt" );
if( inputFile )
{
    while( getline( inputFile, word ) )
    {
        for( i = 0; i < (word.length()- 3); ++i )
        {
            for( k = 0; k < 4; ++k )
                newWord[k] = word[i+k];
            cout << newWord << endl;
            outputFile << newWord << endl;
        }
    }
}
return 0;
}

asked Feb 27, 2013 at 1:47

user1560249's user avatar

user1560249user1560249

3432 gold badges5 silver badges14 bronze badges

12

newWord[k]

The size of the newWord string is zero. The behavior of indexing beyond the end of a std::string is not defined.

You may need to resize the string, thus:

newWord.resize(5);

answered Feb 27, 2013 at 1:50

Robᵩ's user avatar

RobᵩRobᵩ

164k20 gold badges241 silver badges310 bronze badges

The error is because newWord[k] = word[i+k]; does not allocate a space for the string in newWord. The string length is 0, and it is undefined behaviour to do this. Use .append instead.

From cplusplus.com:

If pos is not greater than the string length, the function never
throws exceptions (no-throw guarantee).Otherwise, it causes undefined
behavior.

In the case of newWord[k], pos is k.

This is easy to avoid by using the append function in the string lib.

From cplusplus.com, again:

string& append (const string& str); //Appends a copy of str.

answered Feb 27, 2013 at 1:51

David D's user avatar

David DDavid D

1,57111 silver badges12 bronze badges

Понравилась статья? Поделить с друзьями:
  • String memory leak after effects ошибка
  • Stunnel ошибка 1067 процесс был неожиданно завершен
  • Street power football ошибка соединения облачных сохранений
  • String indices must be integers python ошибка
  • String could not be parsed as xml ошибка