27

Visual Studio 2008 を使用しています。

std::vector には at() 関数による境界チェックがあり、演算子 [] を誤って (範囲外で) 使用して何かにアクセスしようとすると、未定義の動作になることを認識しています。

境界チェックを使用してプログラムをコンパイルできるかどうか興味があります。このように operator[] は at() 関数を使用し、何かが範囲外になるたびに std::out_of_range をスローします。

release モードは operator[] の境界チェックなしでコンパイルされるため、パフォーマンスは低下しません。

Borland C++ を使用して作成されたアプリを Visual Studio に移行しているため、これについて考え始めました。これはコードのごく一部です (i=0、j=1):

v[i][j]; //v is a std::vector<std::vector<int> >

ベクトル 'v' のサイズは [0][1] です (したがって、ベクトルの要素 0 には要素が 1 つしかありません)。これは未定義の動作ですが、Borland はここで 0 を返し、VS はクラッシュしています。私は 0 を返すよりもクラッシュの方が好きなので、std::out_of_range 例外がスローされることでより多くの「クラッシュ」を取得できれば、移行はより速く完了します (したがって、Borland が隠していたより多くのバグが明らかになります)。

4

5 に答える 5

28

Visual Studio 2005 および 2008では、デバッグ ビルドとリリース ビルドの両方operator[]で、既定で境界チェックが既に行われています。

この動作を制御するマクロは_SECURE_SCL. 境界チェックを無効にするには、0 に設定します。

VS2010 での彼らの現在の計画は、リリース ビルドではデフォルトで境界チェックを無効にすることですが、デバッグではそのままにしておくことです。(マクロの名前も に変更されて_ITERATOR_DEBUG_LEVELいます。正式なドキュメントがまだあるかどうかはわかりませんが、ここここで言及されています)

于 2009-08-17T21:33:45.887 に答える
15

ここで説明されているように、フラグ _GLIBCXX_DEBUG を有効にして STL コンテナーの境界チェックを行います: http://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html

于 2010-04-17T03:20:23.987 に答える
4

私はこれを時期尚早に尋ねましたが、とにかく答えを投稿しているので、知識を共有しています。

Visual Studio で実装された stl は、デバッグ モードでコンパイルするときに既に境界チェックを行っています。<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));
        }

そのため、ベクトル クラスの境界チェックがあります。他のコンテナは見ていませんが、同じメカニズムを持っていると確信しています。

于 2009-08-17T21:13:41.293 に答える
0

現在、どの Windows マシンにもアクセスできません。しかし、/usr/include/c++/4.0.0/bits/stl_vector.h から、私の mac os x マシンで g++ とともに提供された STL 実装を調べると、次のようになります。

  // 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 マクロはチェックアウトされていません。

MSVC で提供される独自の STL 実装を見て、何が行われたかを確認してください。いずれの場合もチェックが実行されない場合... at()..を使用するしかありません:-(

于 2009-08-17T21:14:52.633 に答える
-4

C++ では、速度のために例外をスローしないように vector operator[] を定義しています。

主要な「隠れた」バグがなくなったことを確信できるまで、アプリケーションをデバッグ構成でしばらくテストすることをお勧めします。

于 2009-08-17T21:10:02.847 に答える