Iteradores activados

Los iteradores comprobados garantizan que los límites del contenedor no se han sobrescrito.

Los iteradores comprobados se aplican a las compilaciones de depuración y de lanzamiento. Para obtener más información sobre cómo usar iteradores cuando se compila en modo depuración, vea Compatibilidad de los iteradores de depuración.

Comentarios

Para obtener información sobre cómo deshabilitar las advertencias generadas por iteradores comprobados, vea _SCL_SECURE_NO_WARNINGS.

Puede utilizar el símbolo siguiente con la característica iteradores comprobados.

  • _SECURE_SCL
    Si _SECURE_SCL se define como 1, el uso no seguro de iteradores produce un error en tiempo de ejecución y el programa finaliza. Si se define como 0, se deshabilitan los iteradores comprobados. De forma predeterminada, el valor de _SECURE_SCL es 0 para las versiones de lanzamiento y 1 para las versiones de depuración.

Importante

Use _ITERATOR_DEBUG_LEVEL para controlar _SECURE_SCL.Para obtener más información, vea _ITERATOR_DEBUG_LEVEL.

Cuando _SECURE_SCL se define como 1, se realizan las comprobaciones siguientes de SCL:

  • Se comprueban todos los iteradores estándar (por ejemplo, vector::iterator).

  • Si un iterador de salida es un iterador comprobado, se obtendrá un comportamiento comprobado en las llamadas a la función estándar (por ejemplo, std::copy).

  • Si el iterador de salida es un iterador no comprobado, las llamadas a la función estándar producirán advertencias del compilador.

  • Las siguientes funciones producirán un error en tiempo de ejecución si hay algún acceso que sobrepase los límites del contenedor:

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

Cuando _SECURE_SCL se define como 0:

  • Todos los iteradores estándar son no comprobados (los iteradores pueden moverse más allá de los límites del contenedor, lo que da lugar a un comportamiento no definido).

  • Si un iterador de salida es un iterador comprobado, obtendrá un comportamiento comprobado en las llamadas a la función estándar (por ejemplo, std::copy).

  • Si un iterador de salida es un iterador no comprobado, obtendrá un comportamiento no comprobado en las llamadas a la función estándar (por ejemplo, std::copy).

Un iterador comprobado hace referencia a un iterador que llama a invalid_parameter_handler si se intentan sobrepasar los límites del contenedor. Para obtener más información sobre invalid_parameter_handler, vea Validación de parámetros.

checked_array_iterator (Clase) y unchecked_array_iterator (Clase) son los adaptadores de iterador que admiten iteradores comprobados.

Ejemplo

Cuando se compila con _SECURE_SCL 1, se producirá un error en tiempo de ejecución si se intenta el acceso a un elemento que está fuera de los límites del contenedor mediante el operador de indización de algunas clases.

// checked_iterators_1.cpp
// cl.exe /Zi /MDd /EHsc /W4
 
#define _ITERATOR_DEBUG_LEVEL 1
// implies #define _SECURE_SCL 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
};

Este programa imprimirá “67" y después mostrará un cuadro de diálogo de error de aserción con información adicional sobre el error.

De igual forma, cuando se compila con _SECURE_SCL 1, se producirá un error en tiempo de ejecución si se intenta tener acceso a un elemento usando el principio o el final de algunas clases cuando el contenedor está vacío.

// checked_iterators_2.cpp
// cl.exe /Zi /MDd /EHsc /W4
 
#define _ITERATOR_DEBUG_LEVEL 1
// implies #define _SECURE_SCL 1
 
#include <vector>
#include <iostream>
 
using namespace std;
 
int main() 
{
    vector<int> v;
 
    int& i = v.front(); // triggers invalid parameter handler
};

Este programa mostrará un cuadro de diálogo de error de aserción con información adicional sobre el error.

En el código siguiente se muestran distintos escenarios de casos de uso de un iterador con comentarios sobre cada uno.

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

Salida

Si el código mostrado en la sección anterior se compila con cl.exe /EHsc /W4 /MTd, se obtendrá la siguiente advertencia del compilador, pero se compilará sin errores una aplicación ejecutable:

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'

Cuando se ejecutan los resultados de la aplicación de consola, se obtiene lo siguiente:

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

Vea también

Referencia

Información general sobre la biblioteca estándar de C++

Compatibilidad de los iteradores de depuración