Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Стандарт Cpp: выход индекса массива за пределы


Автор: alex7851 5.2.2012, 20:24
Приветствую уважаемую публику.
Возник спор по поводу того, что говорится в последнем стандарте C++ про выход индекса массива за декларированные пределы. Насколько я помню, такой выход допустим (вернее, по стандарту, компилятор не обязан это проверять). Прошу знатоков ткнуть носом, где про это прямо сказано, либо сказать, что такое разрешено, потому что не запрещено стандартом.
Просто мои аргументы в споре иссякли. =)

Автор: boostcoder 5.2.2012, 20:41
Цитата(alex7851 @  5.2.2012,  20:24 Найти цитируемый пост)
про выход индекса массива

в случае автоматического массива - получите segfolt/access_violation/порчу чужой памяти.
в случае с динамическим массивом - получите segfolt/access_violation/порчу чужой памяти.
в случае с вектором - получите segfolt/access_violation/порчу чужой памяти.
в случае с std::array - получите segfolt/access_violation/порчу чужой памяти.

Добавлено через 2 минуты и 49 секунд
подкорректировал.

Добавлено через 3 минуты и 57 секунд
Цитата(alex7851 @  5.2.2012,  20:24 Найти цитируемый пост)
ткнуть носом, где про это прямо сказано

в стандарте. лень искать smile

Автор: alex7851 5.2.2012, 20:57
Спасибо, то, что можно повредить память, очевидно.

Тогда подтвердите, пожалуйста, следующее (если верно smile ):
По стандарту языка, выход за пределы не должен проверяться. Поэтому компиляторы, соответветствующие стандарту, этого не проверяют. Это приводит к тому, что такой код всегда скомпилируется и, если и произойдет ошибка, то только выполнения. Другими словами, можно сказать, что проверка выхода индекса за допустимые пределы не предусмотрена языком C++.

Автор: boostcoder 5.2.2012, 20:59
Цитата(alex7851 @  5.2.2012,  20:57 Найти цитируемый пост)
По стандарту языка, выход за пределы не должен проверяться. Поэтому компиляторы, соответветствующие стандарту, этого не проверяют. Это приводит к тому, что такой код всегда скомпилируется и, если и произойдет ошибка, то только выполнения.

угу.

Цитата(alex7851 @  5.2.2012,  20:57 Найти цитируемый пост)
Другими словами, можно сказать, что проверка выхода индекса за допустимые пределы не предусмотрена языком C++.

ага.

Автор: volatile 6.2.2012, 00:20
Цитата(alex7851 @  5.2.2012,  20:57 Найти цитируемый пост)
Поэтому компиляторы, соответветствующие стандарту, этого не проверяют. 

А компилятор просто не может этого проверить. Выход за пределы может быть проверен, в общем случае, только в ран-тайме. Ну а покуда С/С++ нацелен на максимальное быстродействие, никакой проверки, по-умолчанию нет.
В С++ вообще ничего нет, что не заказывали явно, тем более нагружающее ран-тайм.
Нужна проверка организуйте сами.

Автор: mes 6.2.2012, 01:49
Цитата(boostcoder @  5.2.2012,  19:41 Найти цитируемый пост)
в случае с вектором -

для честности нужно упомянуть еще и std::vector::at()


Автор: boostcoder 6.2.2012, 09:39
mes, как бы да. но это ведь не индекс, и не оператор индекса.

Автор: mes 6.2.2012, 10:09
Цитата(boostcoder @  6.2.2012,  08:39 Найти цитируемый пост)
как бы да. но это ведь не индекс, и не оператор индекса

Цитата


public member function
      reference operator[] ( size_type n );
const_reference operator[] ( size_type n ) const;
Access element

Returns a reference to the element at position n in the vector container.

A similar member function, vector::at, has the same behavior as this operator function, except that vector::at signals if the requested position is out of range by throwing an exception.

 smile 

Автор: xvr 6.2.2012, 13:59
Цитата(alex7851 @  5.2.2012,  20:57 Найти цитируемый пост)
 Другими словами, можно сказать, что проверка выхода индекса за допустимые пределы не предусмотрена языком C++. 

В стандарте это скорее всего будет задеклалрированно как Undefined Behavior (IMHO). Т.е. компилятор имеет право сделать все, что ему заблагорассудится. В том числе может и проверять, а может и не проверять.

Автор: bsa 6.2.2012, 15:13
Очень может быть, что в режиме отладки он проверяет, а в релизе нет.

Автор: fish9370 6.2.2012, 19:39
Цитата(bsa @  6.2.2012,  15:13 Найти цитируемый пост)
Очень может быть, что в режиме отладки он проверяет, а в релизе нет.


в режиме отладки это дебагер, а компилятор такой фигней не страдает..  smile 

Автор: mes 6.2.2012, 20:33
Цитата(fish9370 @  6.2.2012,  18:39 Найти цитируемый пост)
в режиме отладки это дебагер, а компилятор такой фигней не страдает..  

чиго ? smile 

Автор: fish9370 6.2.2012, 21:21
Цитата(mes @  6.2.2012,  20:33 Найти цитируемый пост)
чиго ?


что чиго?  smile 

Автор: mes 6.2.2012, 22:05
Цитата(fish9370 @  6.2.2012,  20:21 Найти цитируемый пост)
что чиго? 

с каких пор компиляцей в режиме отладки занимается дебагер ?

Автор: fish9370 6.2.2012, 22:11
Цитата(mes @  6.2.2012,  22:05 Найти цитируемый пост)
с каких пор компиляцей в режиме отладки занимается дебагер ?


Цитата(bsa @  6.2.2012,  15:13 Найти цитируемый пост)
Очень может быть, что в режиме отладки он проверяет, а в релизе нет.


а что такое проверяет в режиме отладки? 
кто про компиляцию хоть слово сказал?

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

Автор: mes 6.2.2012, 23:32
Цитата(fish9370 @  6.2.2012,  21:11 Найти цитируемый пост)
а что такое проверяет в режиме отладки? 

генерирует код осуществляюий проверку массивов..

Цитата(fish9370 @  6.2.2012,  21:11 Найти цитируемый пост)
кто про компиляцию хоть слово сказал?

оба нижеприведенных режима имеют непосредтсвенное отношение именно к компиляции
Цитата(bsa @  6.2.2012,  14:13 Найти цитируемый пост)
режиме отладки он проверяет, а в релизе

плюс помимо этого явно и многочислено следует из контекста smile

Цитата(fish9370 @  6.2.2012,  21:11 Найти цитируемый пост)
 как это мог бы проверить компилятор? чисто теоретически, если предположить, что существует такой компилятор, который это делает.. 

у массивов запросто smile  также у вектора без вопросов.. немножко проблема когда идет обращение к массиву через указатель, но и тут могут добраться к размеру выделенной  динамической памяти.. (правда последнее это косвенный эффект)... 


Автор: volatile 7.2.2012, 00:44
Код

int main
{
   int arr [] = {1,3,5,7,11};
   int i;
   cin >> i;
   cout << arr [i];
}

Каким образом здесь компилятор может что-то проверить?
И что он должен делать, если ... smile 

Автор: mes 7.2.2012, 01:48
Цитата(volatile @  6.2.2012,  23:44 Найти цитируемый пост)
И что он должен делать, если ...  

исключение, доступ не к своей памяти.. 

Цитата(volatile @  6.2.2012,  23:44 Найти цитируемый пост)
Каким образом здесь компилятор может что-то проверить?

Код



template <typename T, size_t N> 
T& at(T (&arr)[N], size_t n) 
{
   if (n<N) return arr[n];

   throw "out of range";
}


int arr[] = { 10,20,30,40,50,60 };

int main ()
{
   std::cout << at(arr,5)<<std::endl;
   std::cout << at(arr,9)<<std::endl;
}

http://liveworkspace.org/code/34c43666aab4218f34a377122bbf41d2

Автор: volatile 7.2.2012, 02:05
mes, ну это понятно, что можно напридумать черте-что...

Прелесть языка С/С++ (в отличии от бейсика и иже с ним) и заключается в том, что когда программер пишет

Цитата(volatile @  7.2.2012,  00:44 Найти цитируемый пост)
  int arr [] = {1,3,5,7,11};
   int i;
   cin >> i;
   cout << arr [i];

это означает ровно столько, сколько написано, и не разворачивается в 
Цитата(mes @  7.2.2012,  01:48 Найти цитируемый пост)
template <typename T, size_t N> 
T& at(T (&arr)[N], size_t n) 
{
   if (n<N) return arr[n];

   throw "out of range";
}

int arr[] = { 10,20,30,40,50,60 };

int main ()
{
   std::cout << at(arr,5)<<std::endl;
   std::cout << at(arr,9)<<std::endl;
}

Слава богу, что компиляторы C++ еще до такого не доросли, и очень надеюсь не дорастут.

Ужос! smile 

Автор: mes 7.2.2012, 02:27
Цитата(volatile @  7.2.2012,  01:05 Найти цитируемый пост)
Прелесть языка С/С++ (в отличии от бейсика и иже с ним) и заключается в том, что когда программер пишет

1. 
Цитата(fish9370 @  6.2.2012,  21:11 Найти цитируемый пост)
как это мог бы проверить компилятор? чисто теоретически, если предположить, что существует такой компилятор, который это делает.. 

2. выше приводился пример вектора, так  в дебаге вполне ожидаема проверка на выход из диапазона
3. еще проверка на порчу стека и кучи.. хотя это уже косвенно..

Автор: volatile 7.2.2012, 02:55
Ну то что теоретически это можно проверить, понятно. И таких компиляторов куча.
Взять любой продвинутый язык, тот-же бейсик smile
Но это, строго говоря, уже не компилятор.. а генератор, незатребованного кода.

Цитата(mes @  7.2.2012,  02:27 Найти цитируемый пост)
выше приводился пример вектора, так  в дебаге вполне ожидаема проверка на выход из диапазона

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

Цитата(mes @  7.2.2012,  02:27 Найти цитируемый пост)
еще проверка на порчу стека и кучи.. 

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

Автор: fish9370 7.2.2012, 07:41
mes, я не стану тебя переубеждать, просто еще раз скажу свою точку зрения - компиляторы этого не делают, иначе бы не стояла бы столь остро проблема переполнения беферов.. вычислить индексное переполнение в большинстве случаев невозможно, поскольку память на тот момент может быть вобще еще не выделена..


Цитата(volatile @  7.2.2012,  02:55 Найти цитируемый пост)
При выходе за пределы страницы, срабатывает аппаратноя защита.


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


Автор: borisbn 7.2.2012, 08:33
Цитата(fish9370 @  7.2.2012,  07:41 Найти цитируемый пост)
к несчастью, это самая безобидная вещь, которая может случиться с программой после переполнения..

 smile 
http://liveworkspace.org/code/4e6c5db52ce436e12b231a339608c2a7

Автор: mes 7.2.2012, 15:59
Цитата(fish9370 @  7.2.2012,  06:41 Найти цитируемый пост)
 просто еще раз скажу свою точку зрения - компиляторы этого не делают, иначе бы не стояла бы столь остро проблема переполнения буферов.. 

не путайте проблемы выхода за пределы массива, и  обращения по смещеному указетелю..  то что в обоих случае может использоваться оператор[] не ставит оба случая на один уровень.. 

Цитата(volatile @  7.2.2012,  01:55 Найти цитируемый пост)
а не насильно ему втюхивают, то что он не заказывал

ну да!  конечно!  smile только ведь подобный заказ для стандартных массивов легко осуществить хотя бы прагмой ;)
давайте не будем зациклины на C++-way, а смотреть на ситуацию шире ?

Цитата(volatile @  7.2.2012,  01:55 Найти цитируемый пост)
Насчет вектора, ну это вообще, можно сказать пользовательский тип,

опять всего лишь упираемся в то, что нельзя перегружать оператор [] вне класса..


Автор: volatile 7.2.2012, 23:33
mes, у нас с вами в общем-то нет спора. Вопрос просто в терминологии.
Я хотел сказать что компилятор, не может в общем случае, проверить выход за пределы массива, в компайл-тайме.
А в ран-тайме он просто не имеет права добавлять какой-то посторонний код.
Вот и все. Иначе это будет уже не компилятор С++  smile
Хорошо это или плохо, это другой вопрос.
Возможно где-то это и хорошо. Но не в С++.  smile
Потому и люблю С++.
А тем кому нужны всевозможные проверки, (и как результат тормозные приложения), есть очень много других замечательных языков.

Автор: mes 8.2.2012, 00:52
Цитата(volatile @  7.2.2012,  22:33 Найти цитируемый пост)
А в ран-тайме он просто не имеет права добавлять какой-то посторонний код.
Вот и все. Иначе это будет уже не компилятор С++  

только вот непойму почему для дебаг версии не может быть опция оной проверки ?

Добавлено через 7 минут и 11 секунд
я считаю что дебажную проверку выхода за границу в С++ не добавлют к С-масивам, не потому что это лишние расходы, а потому что  акцент использования переложен на соответсвующие контейнеры, и в частности std::array..

Автор: volatile 8.2.2012, 01:41
Цитата(mes @  8.2.2012,  00:52 Найти цитируемый пост)
только вот непойму почему для дебаг версии не может быть опция оной проверки ?

да в дебаге то ради бога. пусть будет какая-угодно проверка.

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

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

Автор: mes 8.2.2012, 01:54
Цитата(volatile @  8.2.2012,  00:41 Найти цитируемый пост)

да в дебаге то ради бога. пусть будет какая-угодно проверка.

так я про то и грил изначально 
smile
Цитата(volatile @  8.2.2012,  00:41 Найти цитируемый пост)

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

знакомо)

Автор: boostcoder 8.2.2012, 02:04
Цитата(volatile @  8.2.2012,  01:41 Найти цитируемый пост)
дебаг использую очень редко

раньше тоже так мыслил. но что-то втянулся)
логи использую в основном при отладке многопоточного кода. ибо дебагеры сходят с ума smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)