偵錯迭代器支援

Visual C++ 執行階段程式庫可在執行階段偵測不正確的迭代器用法、進行判斷提示並顯示對話方塊。 若要啟用偵錯迭代器支援,您必須使用 C++ 標準程式庫和 C 執行階段程式庫的偵錯版本來編譯您的程式。 如需詳細資訊,請參閱 CRT 程式庫功能。 如需如何使用已檢查的迭代器的資訊,請參閱已檢查的迭代器

C++ 標準說明為何成員函式可能會導致容器的迭代器變成無效。 以下為兩個範例:

  • 從容器清除元素時,會導致迭代器的元素變成無效。

  • 使用 push 或 insert 增加向量的大小時,會導致 vector 內的迭代器變成無效。

不正確反覆運算器

如果您在偵錯模式中編譯此範例程式,程式就會在執行階段進行判斷提示並終止。

// iterator_debugging_0.cpp
// compile by using /EHsc /MDd
#include <vector>
#include <iostream>

int main() {
   std::vector<int> v {10, 15, 20};
   std::vector<int>::iterator i = v.begin();
   ++i;

   std::vector<int>::iterator j = v.end();
   --j;

   std::cout << *j << '\n';

   v.insert(i,25);

   std::cout << *j << '\n'; // Using an old iterator after an insert
}

使用_ITERATOR_DEBUG_LEVEL

您可以使用前置處理器巨集 _ITERATOR_DEBUG_LEVEL,來關閉偵錯組建中的迭代器偵錯功能。 此程式不會判斷提示,但仍會觸發未定義的行為。

// iterator_debugging_1.cpp
// compile by using: /EHsc /MDd
#define _ITERATOR_DEBUG_LEVEL 0
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v {10, 15, 20};

   std::vector<int>::iterator i = v.begin();
   ++i;

   std::vector<int>::iterator j = v.end();
   --j;

   std::cout << *j << '\n';

   v.insert(i,25);

   std::cout << *j << '\n'; // Using an old iterator after an insert
}
20
-572662307

未初始化的反覆運算器

如果您嘗試在初始化反覆運算器之前使用反覆運算器,也會發生判斷提示,如下所示:

// iterator_debugging_2.cpp
// compile by using: /EHsc /MDd
#include <string>
using namespace std;

int main() {
   string::iterator i1, i2;
   if (i1 == i2)
      ;
}

不相容的反覆運算器

下列程式碼範例會引起判斷提示,因為針對 for_each 演算法提供的兩個迭代器不相容。 演算法會檢查並判斷會提供給它們的迭代器是否參考相同的容器。

// iterator_debugging_3.cpp
// compile by using /EHsc /MDd
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
    vector<int> v1 {10, 20};
    vector<int> v2 {10, 20};

    // The next line asserts because v1 and v2 are
    // incompatible.
    for_each(v1.begin(), v2.end(), [] (int& elem) { elem *= 2; } );
}

請注意,此範例中使用 Lambda 運算式[] (int& elem) { elem *= 2; } 而不是仿函式。 雖然這個選擇與判斷提示失敗沒有關系,但類似的函式會導致相同的失敗,但 Lambda 是撰寫簡短程式碼區塊的方法。 如需 Lambda 運算式的詳細資訊,請參閱 Lambda 運算式

反覆運算器離開範圍

for 迴圈範圍結束時,偵錯迭代器的檢查也會導致 for 迴圈中宣告的迭代器變數超出範圍。

// iterator_debugging_4.cpp
// compile by using: /EHsc /MDd
#include <vector>
#include <iostream>
int main() {
   std::vector<int> v {10, 15, 20};

   for (std::vector<int>::iterator i = v.begin(); i != v.end(); ++i)
      ;   // do nothing
   --i;   // C2065
}

偵錯反覆運算器的解構函式

偵錯迭代器具有非一般的解構函式。 如果解構函式未執行,但釋放物件的記憶體,可能會發生存取違規和資料損毀。 請考慮此範例:

// iterator_debugging_5.cpp
// compile by using: /EHsc /MDd
#include <vector>
struct base {
   // TO FIX: uncomment the next line
   // virtual ~base() {}
};

struct derived : base {
   std::vector<int>::iterator m_iter;
   derived( std::vector<int>::iterator iter ) : m_iter( iter ) {}
   ~derived() {}
};

int main() {
   std::vector<int> vect( 10 );
   base * pb = new derived( vect.begin() );
   delete pb;  // doesn't call ~derived()
   // access violation
}

另請參閱

C++ 標準程式庫概觀