Как заставить std::vector's operator[] компилироваться, проверяя границы в DEBUG, но не в RELEASE
-
18-09-2019 - |
Вопрос
Я использую Visual Studio 2008.
Я знаю, что std::vector проверяет границы с помощью функции at () и имеет неопределенное поведение, если вы пытаетесь получить доступ к чему-либо, используя оператор [] неправильно (вне диапазона).
Мне любопытно, возможно ли скомпилировать мою программу с проверкой границ.Таким образом, оператор[] будет использовать функцию at() и выдавать std::out_of_range всякий раз, когда что-то выходит за рамки.
Режим выпуска будет скомпилирован без проверки границ для operator[], поэтому производительность не ухудшится.
Я задумался об этом, потому что я переношу приложение, написанное с использованием Borland C ++, в Visual Studio, и в небольшой части кода у меня есть это (с i = 0, j = 1):
v[i][j]; //v is a std::vector<std::vector<int> >
Размер вектора 'v' равен [0][1] (таким образом, элемент 0 вектора имеет только один элемент).Я знаю, что это неопределенное поведение, но Borland возвращает здесь 0, VS выходит из строя.Сбой мне нравится больше, чем возврат 0, поэтому, если я смогу получить больше "сбоев" из-за генерируемого исключения std::out_of_range, миграция будет завершена быстрее (так что это выявит больше ошибок, которые скрывал Borland).
Решение
Visual Studio 2005 и 2008 уже выполняют проверку границ на operator[]
по умолчанию в и то, и другое отлаживайте и выпускайте сборки.
Макрос для управления этим поведением является _SECURE_SCL
.Установите для него значение 0, чтобы отключить проверку границ.
Их текущий план в VS2010 состоит в том, чтобы отключить проверку границ по умолчанию в сборках release, но сохранить ее включенной в debug.(Макрос также переименовывается в _ITERATOR_DEBUG_LEVEL
.Я не знаю, есть ли еще какая-либо официальная документация по этому поводу, но об этом упоминалось здесь и здесь)
Другие советы
Включите флаг _GLIBCXX_DEBUG для проверки границ контейнеров STL, как описано здесь:http://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html
Я задал этот вопрос слишком преждевременно, но я все равно публикую ответ, поэтому делюсь некоторыми знаниями.
stl, реализованный в Visual Studio, уже выполняет проверку границ при компиляции в режиме отладки.Это можно увидеть на <vector>
заголовок:
reference operator[](size_type _Pos)
{ // subscript mutable sequence
#if _HAS_ITERATOR_DEBUGGING
if (size() <= _Pos)
{
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}
#endif /* _HAS_ITERATOR_DEBUGGING */
_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
return (*(_Myfirst + _Pos));
}
итак, есть проверка границ для векторного класса.Я не смотрел на другие контейнеры, но я уверен, что у них такой же механизм.
Прямо сейчас у меня нет доступа ни к одному компьютеру с Windows.Но если я посмотрю на реализацию STL, поставляемую с g ++ на моем компьютере mac os x, из / usr/include/c ++ / 4.0.0/bits/stl_vector.h :
// element access
/**
* @brief Subscript access to the data contained in the %vector.
* @param n The index of the element for which data should be
* accessed.
* @return Read/write reference to data.
*
* This operator allows for easy, array-style, data access.
* Note that data access with this operator is unchecked and
* out_of_range lookups are not defined. (For checked lookups
* see at().)
*/
reference
operator[](size_type __n)
{ return *(begin() + __n); }
Проверка не выполнена, событие, хотя и в режиме отладки.Здесь, в этом коде, маркер _GLIBCXX_DEBUG не проверен.
Взгляните на свою собственную реализацию STL, поставляемую с MSVC, и посмотрите, что сделано.Если в любом случае проверка не будет произведена ...у вас нет выбора, кроме как использовать at()..:-(
C ++ определяет векторный оператор[] как не выбрасывающий исключение ради скорости.
Я бы посоветовал вам протестировать приложение в конфигурации отладки некоторое время, пока вы не обретете уверенность в том, что основные "скрытые" ошибки устранены.