Подтвердить что ты не робот

Как сделать оператор 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).

4b9b3361

Ответ 1

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

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

Их текущий план в VS2010 состоит в том, чтобы отключить проверку границ по умолчанию в сборках релизов, но сохранить его при отладке. (Макрос также переименовывается в _ITERATOR_DEBUG_LEVEL. Я не знаю, есть ли там формальная документация, но было упомянуто здесь и здесь)

Ответ 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, пока не получите уверенность в том, что основные "скрытые" ошибки исчезли.