2015-07-30 3 views
-6

Почему это:Доступ к из диапазона массива не дает никакой ошибки

#include <iostream> 
using namespace std; 

int main() { 
    int a[1] = {0}; 
    a[2048] = 1234; 

    cout << a[2048] << endl; 

    return 0; 
} 

не дает никаких во время компиляции ошибки? (gcc 4.9.3)

+2

Зачем? Компилятор не дает двух криков, хотите ли вы стрелять в ногу. * Вы * решили использовать * неопределенное поведение *. Что посеешь то и пожнешь. Если это сработает, вам повезло. – WhozCraig

+0

С clang есть предупреждение, называемое array-bounds, которое делает именно это. –

ответ

2

Потому что это законный C++.
Вы можете попытаться разыменовать любой указатель, даже если он не выделен вашей программой, вы можете попытаться получить доступ к любой ячейке массива, даже если это вне пределов, законность выражения не зависит от значений переменных, участвующих в этом выражении.
Компилятор не должен запускать какой-либо статический анализ, чтобы проверить, действительно ли вы будете вызывать неопределенное поведение или нет, и не должен компилироваться, если он предполагает, что вы это сделаете (даже если это очевидно, что вы это сделаете).
Проблема в том, что вы не можете проверить доступ к любому доступному массиву во время компиляции (это было бы слишком дорого), поэтому вам придется произвольно нарисовать строку где-нибудь (проблема заключается в слове «произвольно», что не будет хорошо соответствовать стандарту).
Следовательно, проверка того, что вы не будете вызывать неопределенное поведение, - это ответственность программиста (или конкретных инструментов статического анализа).

+0

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

+0

Нет, это не так. Однако, если вы можете это проверить, вы можете утверждать, что вы можете проверить все, что является constexpr. Тогда вы можете утверждать, что можете выполнить базовый статический анализ для дальнейшего улучшения этого. Тогда вы можете утверждать, что можете запустить полноценный инструмент статического анализа, потому что это даст наилучшие результаты. Проблема в том, что стандарт не имеет права решать компромисс между временем компиляции/статическим анализом. Вы все еще можете статически проверять свой код, но для этого вам придется использовать инструмент статического анализа, это не работа компилятора. – Caninonos

+0

Тем не менее, я должен признать, предупреждение было бы интересно иметь, если статический анализ можно отключить с помощью опций и что это не является жесткой ошибкой. Но опять же, это просто добавление инструмента статического анализа поверх компилятора. Стандарт не имеет права запрашивать у каждого компилятора такой инструмент статического анализа, он должен быть необязательным. – Caninonos

1

доступа вне диапазона массива не дает каких-либо ошибок

Это только потому, что вам не повезло. :) То, что вы можете назвать, это «Неопределенное поведение». Компилятор не выполняет проверку привязки на массивах, и то, что вы пытаетесь сделать в инструкции a[2048] = 1234;, заключается в том, чтобы записать ячейку памяти в стек, которая не используется.