Aracılığıyla paylaş


Denetlenmiş Yineleyiciler

İşaretli yineleyiciler, kapsayıcınızın sınırlarının geçersiz kılınmamasını sağlar. Denetlenen yineleyiciler hem sürüm derlemeleri hem de hata ayıklama derlemeleri için geçerlidir. Hata ayıklama modunda derleme yaparken hata ayıklama yineleyicilerini kullanma hakkında daha fazla bilgi için bkz . Hata Ayıklama Yineleyici desteği.

Açıklamalar

denetlenen yineleyiciler tarafından oluşturulan uyarıları devre dışı bırakma hakkında bilgi için bkz . _SCL_SECURE_NO_WARNINGS.

denetlenen yineleyiciler özelliğini etkinleştirmek veya devre dışı bırakmak için _ITERATOR_DEBUG_LEVEL önişlemci makrosunu kullanabilirsiniz. _ITERATOR_DEBUG_LEVEL 1 veya 2 olarak tanımlanırsa, yineleyicilerin güvenli olmayan kullanımı çalışma zamanı hatasına neden olur ve program sonlandırılır. 0 olarak tanımlanmışsa, işaretli yineleyiciler devre dışı bırakılır. Varsayılan olarak, _ITERATOR_DEBUG_LEVEL değeri sürüm derlemeleri için 0 ve hata ayıklama derlemeleri için 2'dir.

Önemli

Eski belgeler ve kaynak kodu _SECURE_SCL makroya başvurabilir. _SECURE_SCL denetlemek için _ITERATOR_DEBUG_LEVEL kullanın. Daha fazla bilgi için bkz . _ITERATOR_DEBUG_LEVEL.

_ITERATOR_DEBUG_LEVEL 1 veya 2 olarak tanımlandığında, bu yineleyici denetimleri gerçekleştirilir:

  • Tüm standart yineleyiciler (örneğin, vector::yineleyici) denetlendi.

  • Çıkış yineleyicisi denetlenmiş bir yineleyiciyse, std::copy gibi standart kitaplık işlevlerine çağrılar denetim davranışı alır.

  • Çıkış yineleyicisi işaretsiz bir yineleyiciyse, standart kitaplık işlevlerine yapılan çağrılar derleyici uyarılarına neden olur.

  • Aşağıdaki işlevler, kapsayıcı sınırlarının dışında bir erişim varsa bir çalışma zamanı hatası oluşturur:

_ITERATOR_DEBUG_LEVEL 0 olarak tanımlandığında:

  • Tüm standart yineleyicilerin işareti kaldırılır. Yineleyiciler kapsayıcı sınırlarının ötesine geçebilir ve bu da tanımsız davranışa yol açar.

  • Çıkış yineleyicisi denetlenmiş bir yineleyiciyse, denetim davranışı alma gibi std::copy standart kitaplık işlevlerine çağrır.

  • Çıkış yineleyicisi işaretsiz bir yineleyiciyse, standart kitaplık işlevlerine yapılan çağrılar işaretsiz davranış alır.

denetlenen yineleyici, kapsayıcının sınırlarını aşmaya çalışırsanız çağıran invalid_parameter_handler bir yineleyiciye başvurur. hakkında invalid_parameter_handlerdaha fazla bilgi için bkz . Parametre Doğrulama.

Denetlenen yineleyicileri destekleyen yineleyici bağdaştırıcıları Checked_array_iterator Sınıfı ve unchecked_array_iterator Sınıfıdır.

Örnekler

1 veya 2 olarak ayarlanmış _ITERATOR_DEBUG_LEVEL kullanarak derleme yaptığınızda, belirli sınıfların dizin işlecini kullanarak kapsayıcı sınırlarının dışındaki bir öğeye erişmeye çalıştığınızda çalışma zamanı hatası oluşur.

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

Bu program "67" yazdırır ve ardından hata hakkında ek bilgiler içeren bir onay hatası iletişim kutusu açar.

Benzer şekilde, 1 veya 2 olarak ayarlanmış _ITERATOR_DEBUG_LEVEL kullanarak derleme yaptığınızda, kapsayıcı boş olduğunda kapsayıcı sınıflarını kullanarak front veya back kullanarak bir öğeye erişmeye çalıştığınızda bir çalışma zamanı hatası oluşur.

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

Bu program, hata hakkında ek bilgiler içeren bir onay hatası iletişim kutusu açar.

Aşağıdaki kod, her biriyle ilgili yorumlar içeren çeşitli yineleyici kullanım örneği senaryolarını gösterir. Varsayılan olarak, _ITERATOR_DEBUG_LEVEL Hata ayıklama derlemelerinde 2 ve Perakende derlemelerinde 0 olarak ayarlanır.

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

Derleyiciyi kullanarak cl.exe /EHsc /W4 /MTd checked_iterators_3.cpp bu kodu derlediğinizde bir uyarı yayar, ancak hatasız bir yürütülebilir dosyaya derlenir:

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'

Komut satırında çalıştırıldığında yürütülebilir dosya şu çıkışı oluşturur:

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

Ayrıca bkz.

C++ Standart Kitaplığına Genel Bakış
Hata Ayıklama Yineleyici Desteği