Iterator Yang Diperiksa

Iterator yang diperiksa memastikan bahwa batas kontainer Anda tidak ditimpa. Iterator yang diperiksa berlaku untuk build rilis dan build debug. Untuk informasi selengkapnya tentang cara menggunakan iterator debug saat Anda mengkompilasi dalam mode debug, lihat Debug Dukungan Iterator.

Keterangan

Untuk informasi tentang cara menonaktifkan peringatan yang dihasilkan oleh iterator yang diperiksa, lihat _SCL_SECURE_NO_WARNINGS.

Anda dapat menggunakan makro praprosesor _ITERATOR_DEBUG_LEVEL untuk mengaktifkan atau menonaktifkan fitur iterator yang diperiksa. Jika _ITERATOR_DEBUG_LEVEL didefinisikan sebagai 1 atau 2, penggunaan iterator yang tidak aman menyebabkan kesalahan runtime dan program dihentikan. Jika didefinisikan sebagai 0, iterator yang diperiksa dinonaktifkan. Secara default, nilai untuk _ITERATOR_DEBUG_LEVEL adalah 0 untuk build rilis dan 2 untuk build debug.

Penting

Dokumentasi dan kode sumber yang lebih lama dapat merujuk ke makro _SECURE_SCL . Gunakan _ITERATOR_DEBUG_LEVEL untuk mengontrol _SECURE_SCL. Untuk informasi selengkapnya, lihat _ITERATOR_DEBUG_LEVEL.

Ketika _ITERATOR_DEBUG_LEVEL didefinisikan sebagai 1 atau 2, pemeriksaan iterator ini dilakukan:

  • Semua iterator standar (misalnya, vektor::iterator) dicentang.

  • Jika iterator output adalah iterator yang diperiksa, panggilan ke fungsi pustaka standar seperti std::copy get checked behavior.

  • Jika iterator output adalah iterator yang tidak dicentang, panggilan ke fungsi pustaka standar menyebabkan peringatan kompilator.

  • Fungsi berikut menghasilkan kesalahan runtime jika ada akses yang berada di luar batas kontainer:

Saat _ITERATOR_DEBUG_LEVEL didefinisikan sebagai 0:

  • Semua iterator standar tidak dicentang. Iterator dapat bergerak melampaui batas kontainer, yang menyebabkan perilaku yang tidak terdefinisi.

  • Jika iterator output adalah iterator yang diperiksa, panggilan ke fungsi pustaka standar seperti std::copy mendapatkan perilaku yang diperiksa.

  • Jika iterator output adalah iterator yang tidak dicentang, panggilan ke fungsi pustaka standar mendapatkan perilaku yang tidak dicentang.

Iterator yang diperiksa mengacu pada iterator yang memanggil invalid_parameter_handler jika Anda mencoba untuk melewati batas kontainer. Untuk informasi selengkapnya tentang invalid_parameter_handler, lihat Validasi Parameter.

Adaptor iterator yang mendukung iterator yang diperiksa adalah Kelas checked_array_iterator dan Kelas unchecked_array_iterator.

Contoh

Saat Anda mengkompilasi dengan menggunakan _ITERATOR_DEBUG_LEVEL diatur ke 1 atau 2, kesalahan runtime akan terjadi jika Anda mencoba mengakses elemen yang berada di luar batas kontainer dengan menggunakan operator pengindeksan kelas tertentu.

// checked_iterators_1.cpp
// cl.exe /Zi /MDd /EHsc /W4

#define _ITERATOR_DEBUG_LEVEL 1

#include <vector>
#include <iostream>

using namespace std;

int main()
{
   vector<int> v;
   v.push_back(67);

   int i = v[0];
   cout << i << endl;

   i = v[1]; //triggers invalid parameter handler
}

Program ini mencetak "67" lalu memunculkan kotak dialog kegagalan pernyataan dengan informasi tambahan tentang kegagalan tersebut.

Demikian pula, ketika Anda mengkompilasi dengan menggunakan _ITERATOR_DEBUG_LEVEL diatur ke 1 atau 2, kesalahan runtime akan terjadi jika Anda mencoba mengakses elemen dengan menggunakan front atau back di kelas kontainer saat kontainer kosong.

// checked_iterators_2.cpp
// cl.exe /Zi /MDd /EHsc /W4
#define _ITERATOR_DEBUG_LEVEL 1

#include <vector>
#include <iostream>

using namespace std;

int main()
{
   vector<int> v;

   int& i = v.front(); // triggers invalid parameter handler
}

Program ini memunculkan kotak dialog kegagalan pernyataan dengan informasi tambahan tentang kegagalan tersebut.

Kode berikut menunjukkan berbagai skenario kasus penggunaan iterator dengan komentar tentang masing-masing. Secara default, _ITERATOR_DEBUG_LEVEL diatur ke 2 di build Debug, dan ke 0 di Build ritel.

// checked_iterators_3.cpp
// cl.exe /MTd /EHsc /W4

#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <numeric>
#include <string>
#include <vector>

using namespace std;

template <typename C>
void print(const string& s, const C& c)
{
    cout << s;

    for (const auto& e : c) {
        cout << e << " ";
    }

    cout << endl;
}

int main()
{
    vector<int> v(16);
    iota(v.begin(), v.end(), 0);
    print("v: ", v);

    // OK: vector::iterator is checked in debug mode
    // (i.e. an overrun causes a debug assertion)
    vector<int> v2(16);
    transform(v.begin(), v.end(), v2.begin(), [](int n) { return n * 2; });
    print("v2: ", v2);

    // OK: back_insert_iterator is marked as checked in debug mode
    // (i.e. an overrun is impossible)
    vector<int> v3;
    transform(v.begin(), v.end(), back_inserter(v3), [](int n) { return n * 3; });
    print("v3: ", v3);

    // OK: array::iterator is checked in debug mode
    // (i.e. an overrun causes a debug assertion)
    array<int, 16> a4;
    transform(v.begin(), v.end(), a4.begin(), [](int n) { return n * 4; });
    print("a4: ", a4);

    // OK: Raw arrays are checked in debug mode
    // (an overrun causes a debug assertion)
    // NOTE: This applies only when raw arrays are given to C++ Standard Library algorithms!
    int a5[16];
    transform(v.begin(), v.end(), a5, [](int n) { return n * 5; });
    print("a5: ", a5);

    // WARNING C4996: Pointers cannot be checked in debug mode
    // (an overrun causes undefined behavior)
    int a6[16];
    int * p6 = a6;
    transform(v.begin(), v.end(), p6, [](int n) { return n * 6; });
    print("a6: ", a6);

    // OK: stdext::checked_array_iterator is checked in debug mode
    // (an overrun causes a debug assertion)
    int a7[16];
    int * p7 = a7;
    transform(v.begin(), v.end(), stdext::make_checked_array_iterator(p7, 16), [](int n) { return n * 7; });
    print("a7: ", a7);

    // WARNING SILENCED: stdext::unchecked_array_iterator is marked as checked in debug mode
    // (it performs no checking, so an overrun causes undefined behavior)
    int a8[16];
    int * p8 = a8;
    transform(v.begin(), v.end(), stdext::make_unchecked_array_iterator(p8), [](int n) { return n * 8; });
    print("a8: ", a8);
}

Saat Anda mengkompilasi kode ini dengan menggunakan cl.exe /EHsc /W4 /MTd checked_iterators_3.cpp pengkompilasi memancarkan peringatan, tetapi mengkompilasi tanpa kesalahan ke dalam executable:

algorithm(1026) : warning C4996: 'std::_Transform1': Function call with parameters
that may be unsafe - this call relies on the caller to check that the passed values
are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation
on how to use Visual C++ 'Checked Iterators'

Saat dijalankan di baris perintah, executable menghasilkan output ini:

v: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
v2: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
v3: 0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45
a4: 0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60
a5: 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75
a6: 0 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90
a7: 0 7 14 21 28 35 42 49 56 63 70 77 84 91 98 105
a8: 0 8 16 24 32 40 48 56 64 72 80 88 96 104 112 120

Baca juga

Gambaran Umum Pustaka Standar C++
Debug Dukungan Iterator