Как сделать оператор std::vector operator [] компилировать проверку границ в DEBUG, но не в RELEASE
Я использую Visual Studio 2008.
Я знаю, что std::vector имеет проверку границ с помощью функции at() и имеет поведение undefined, если вы пытаетесь получить доступ к чему-либо с помощью оператора [] неправильно (вне диапазона).
Мне интересно, возможно ли скомпилировать мою программу с проверкой границ. Таким образом, оператор [] будет использовать функцию at() и бросать std:: out_of_range всякий раз, когда что-то выходит за пределы.
Режим освобождения будет скомпилирован без проверки границ для оператора [], поэтому производительность не ухудшается.
Я подумал об этом, потому что я переношу приложение, написанное с использованием Borland С++ для Visual Studio, и в небольшой части кода у меня есть это (с я = 0, j = 1):
v[i][j]; //v is a std::vector<std::vector<int> >
Размер вектора 'v' равен [0] [1] (поэтому элемент 0 вектора имеет только один элемент). Это поведение undefined, я знаю, но Borland возвращается 0 здесь, VS сбой. Мне нравится крах лучше, чем возврат 0, поэтому, если я могу получить больше "сбоев" из создаваемого исключения std:: out_of_range, миграция будет завершена быстрее (так что это приведет к появлению большего количества ошибок, которые скрывал Borland).
Ответы
Ответ 1
Visual Studio 2005 и 2008 уже по умолчанию ограничивают проверку на operator[]
в обеих версиях отладки и выпуска.
Макрос для управления этим поведением _SECURE_SCL
. Установите значение 0, чтобы отключить проверку границ.
Их текущий план в VS2010 состоит в том, чтобы отключить проверку границ по умолчанию в сборках релизов, но сохранить его при отладке. (Макрос также переименовывается в _ITERATOR_DEBUG_LEVEL
. Я не знаю, есть ли там формальная документация, но было упомянуто здесь и здесь)
Ответ 2
Включить флаг _GLIBCXX_DEBUG для проверки границ на контейнерах STL, как описано здесь:
http://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html
Ответ 3
Я задал это слишком рано, но я все равно отправляю ответ, чтобы поделиться некоторыми знаниями.
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));
}
поэтому существует проверка границ для векторного класса. Я не смотрел на другие контейнеры, но я уверен, что они имеют тот же механизм.
Ответ 4
У меня нет доступа к любой машине 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); }
Выполнение проверки не выполняется, но в режиме DEBUG. В этом коде нет здесь _GLIBCXX_DEBUG marcro.
Посмотрите в своей собственной реализации STL, поставляемой с MSVC, и посмотрите, что сделано. Если в любом случае проверка не производится, у вас нет выбора, кроме как использовать()..:-(
Ответ 5
С++ определяет векторный оператор [] как исключение исключения для скорости.
Я бы посоветовал вам некоторое время тестировать приложение в Debug Configuration, пока не получите уверенность в том, что основные "скрытые" ошибки исчезли.