Как заставить оператор std::vector [] компилировать, выполняя проверку границ в DEBUG, но не в RELEASE

Я использую Visual Studio 2008.

Мне известно, что std::vector имеет проверку границ с помощью функции at() и имеет неопределенное поведение, если вы пытаетесь получить доступ к чему-либо с помощью оператора [] неправильно (вне диапазона).

Мне любопытно, можно ли скомпилировать мою программу с проверкой границ. Таким образом, оператор [] будет использовать функцию at() и выбрасывать std::out_of_range всякий раз, когда что-то выходит за пределы.

Режим освобождения будет скомпилирован без проверки границ для оператора [], поэтому производительность не ухудшится.

Я задумался об этом, потому что я переносил приложение, написанное с использованием 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, миграция будет завершена быстрее (поэтому будет выявлено больше ошибок, которые скрывал Борланд).

6 ответов

Решение

Visual Studio 2005 и 2008 уже выполняют проверку границ operator[] по умолчанию как в отладочной, так и в выпускной сборках.

Макрос для управления этим поведением _SECURE_SCL, Установите 0, чтобы отключить проверку границ.

Их текущий план в VS2010 состоит в том, чтобы отключить проверку границ по умолчанию в сборках релиза, но оставить его включенным в режиме отладки. (Макрос также переименовывается в _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 marcro не проверяется здесь в этом коде.

Взгляните на свою собственную реализацию STL, поставляемую с MSVC, и посмотрите, что сделано. Если в любом случае проверка не выполняется... у вас нет выбора, кроме как использовать at()..:-(

Для людей, использующих QT, добавьте следующую строку в файл .pro:

      CONFIG(debug, debug|release ):DEFINES += _GLIBCXX_DEBUG

PS Когда я добавил эту строку, компилятор выдал много ошибок. Я удалил все файлы, созданные компилятором, в каталоге сборки, перекомпилировал проект, и ошибки исчезли.

C++ определяет векторный оператор [] как не вызывающий исключение ради скорости.

Я бы посоветовал вам протестировать приложение в конфигурации отладки некоторое время, пока вы не обретете уверенность в том, что основные "скрытые" ошибки исчезли.

Другие вопросы по тегам