Share via


Debug Dukungan Iterator

Pustaka run-time Visual C++ mendeteksi penggunaan iterator yang salah, dan menegaskan dan menampilkan kotak dialog pada waktu proses. Untuk mengaktifkan dukungan iterator debug, Anda harus menggunakan versi debug Pustaka Standar C++ dan Pustaka Runtime C untuk mengkompilasi program Anda. Untuk informasi selengkapnya, lihat Fitur Pustaka CRT. Untuk informasi tentang cara menggunakan iterator yang diperiksa, lihat Iterator Yang Diperiksa.

Standar C++ menjelaskan bagaimana fungsi anggota dapat menyebabkan iterator ke kontainer menjadi tidak valid. Dua contohnya adalah:

  • Menghapus elemen dari kontainer menyebabkan iterator ke elemen menjadi tidak valid.

  • Meningkatkan ukuran vektor dengan menggunakan pendorongan atau penyisipan menyebabkan iterator menjadi vector tidak valid.

Iterator tidak valid

Jika Anda mengkompilasi program sampel ini dalam mode debug, pada waktu proses ia menegaskan dan mengakhiri.

// 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
}

Menggunakan _ITERATOR_DEBUG_LEVEL

Anda dapat menggunakan makro praprosesor _ITERATOR_DEBUG_LEVEL untuk menonaktifkan fitur penelusuran kesalahan iterator dalam build debug. Program ini tidak menegaskan, tetapi masih memicu perilaku yang tidak terdefinisi.

// 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 yang tidak diinisialisasi

Pernyataan juga terjadi jika Anda mencoba menggunakan iterator sebelum diinisialisasi, seperti yang ditunjukkan di sini:

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

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

Iterator yang tidak kompatibel

Contoh kode berikut menyebabkan pernyataan karena dua iterator ke algoritma for_each tidak kompatibel. Algoritma memeriksa untuk menentukan apakah iterator yang diberikan kepada mereka mereferensikan kontainer yang sama.

// 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; } );
}

Perhatikan bahwa contoh ini menggunakan ekspresi [] (int& elem) { elem *= 2; } lambda alih-alih funktor. Meskipun pilihan ini tidak memiliki bantalan pada kegagalan pernyataan —funktor serupa akan menyebabkan kegagalan yang sama —lambda adalah cara untuk menulis blok kode singkat. Untuk informasi selengkapnya tentang ekspresi lambda, lihat Ekspresi Lambda.

Iterator keluar dari cakupan

Pemeriksaan iterator debug juga menyebabkan variabel iterator yang dinyatakan dalam perulangan for berada di luar cakupan saat for cakupan perulangan berakhir.

// 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
}

Destruktor untuk iterator debug

Iterator debug memiliki destruktor non-sepele. Jika destruktor tidak berjalan tetapi memori objek dibesarkan, pelanggaran akses dan kerusakan data mungkin terjadi. Pertimbangkan contoh ini:

// 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
}

Baca juga

Gambaran Umum Pustaka Standar C++