Skip to content

Latest commit

 

History

History
245 lines (188 loc) · 8.99 KB

checked-iterators.md

File metadata and controls

245 lines (188 loc) · 8.99 KB
title Checked Iterators | Microsoft Docs
ms.custom
ms.date 11/04/2016
ms.reviewer
ms.suite
ms.technology
devlang-cpp
ms.tgt_pltfrm
ms.topic article
f1_keywords
_SECURE_SCL
_SECURE_SCL_THROWS
dev_langs
C++
helpviewer_keywords
Safe Libraries
Safe Libraries, Standard C++ Library
Safe Standard C++ Library
iterators, checked
checked iterators
ms.assetid cfc87df8-e3d9-403b-ab78-e9483247d940
caps.latest.revision 30
author corob-msft
ms.author corob
manager ghogen
translation.priority.ht
cs-cz
de-de
es-es
fr-fr
it-it
ja-jp
ko-kr
pl-pl
pt-br
ru-ru
tr-tr
zh-cn
zh-tw

Checked Iterators

Checked iterators ensure that the bounds of your container are not overwritten.

Checked iterators apply to release builds and debug builds. For more information about how to use iterators when you compile in debug mode, see Debug Iterator Support.

Remarks

For information about how to disable warnings that are generated by checked iterators, see _SCL_SECURE_NO_WARNINGS.

You can use the following symbol with the checked iterators feature.

_SECURE_SCL
If _SECURE_SCL is defined as 1, unsafe use of iterators causes a runtime error and the program is terminated. If defined as 0, checked iterators are disabled. By default, the value for _SECURE_SCL is 0 for release builds and 1 for debug builds.

Important

Use _ITERATOR_DEBUG_LEVEL to control _SECURE_SCL. For more information, see _ITERATOR_DEBUG_LEVEL.

When _SECURE_SCL is defined as 1, following SCL checks are performed:

  • All standard iterators (for example, vector::iterator) are checked.

  • If an output iterator is a checked iterator you will get checked behavior on calls to the standard function (for example, std::copy).

  • If the output iterator is an unchecked iterator calls to the standard function will cause compiler warnings.

  • The following functions will generate a runtime error if there is an access that is outside the bounds of the container:

basic_string::operator bitset::operator deque::back deque::front
deque::operator list::back list::front queue::back
queue::front vector::operator vector::back vector::front

When _SECURE_SCL is defined as 0:

  • All standard iterators are unchecked (iterators can move beyond the container boundaries, which leads to undefined behavior).

  • If an output iterator is a checked iterator you will get checked behavior on calls to the standard function (for example, std::copy).

  • If an output iterator is an unchecked iterator you will get unchecked behavior on calls to the standard function (for example, std::copy).

A checked iterator refers to an iterator that will call invalid_parameter_handler if you attempt to move past the boundaries of the container. For more information about invalid_parameter_handler, see Parameter Validation.

checked_array_iterator Class and unchecked_array_iterator Class are the iterator adaptors that support checked iterators.

Example

When you compile by using _SECURE_SCL 1, a runtime error will occur if you attempt to access an element that is outside the bounds of the container by using the indexing operator of certain classes.

//checked_iterators_1.cpp  
//cl.exe/Zi/MDd/EHsc/W4  
  
#define_ITERATOR_DEBUG_LEVEL1  
//implies#define_SECURE_SCL1  
  
#include<vector>  
#include<iostream>  
  
usingnamespacestd;  
  
intmain()  
{  
vector<int>v;  
v.push_back(67);  
  
inti=v[0];  
cout<<i<<endl;  
  
i=v[1];//triggersinvalidparameterhandler  
};  
  

This program will print out "67" then pop an assertion failure dialog box with additional information about the failure.

Example

Similarly, when you compile by using _SECURE_SCL 1, a runtime error will occur if you attempt to access an element by using front or back of certain classes, when the container is empty.

//checked_iterators_2.cpp  
//cl.exe/Zi/MDd/EHsc/W4  
  
#define_ITERATOR_DEBUG_LEVEL1  
//implies#define_SECURE_SCL1  
  
#include<vector>  
#include<iostream>  
  
usingnamespacestd;  
  
intmain()  
{  
vector<int>v;  
  
int&i=v.front();//triggersinvalidparameterhandler  
};  
  

This program will pop up an assertion failure dialog box with additional information about the failure.

The following code demonstrates various iterator use-case scenarios with comments about each.

//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 will trigger 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 will trigger 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 will trigger a debug assertion)  
    // NOTE: This applies only when raw arrays are given to STL 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 will trigger 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 will trigger 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 will trigger 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);  
}  
  

Output

Compiling the code shown in the previous section with cl.exe /EHsc /W4 /MTd will result in the following compiler warning, but compiles without error into an executable:

algorithm(1026) : warning C4996: 'std::_Transform1': Function call with parameters that may be unsafe - this call rel  
ies 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'  

Running the console app executable results in the following output:

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  

See Also

STL Overview
Debug Iterator Support