Compartir vía


Compatibilidad de los iteradores de depuración

La biblioteca en tiempo de ejecución de Visual C++ detecta un uso incorrecto del iterador, valida y muestra un cuadro de diálogo en tiempo de ejecución. Para habilitar la compatibilidad con el iterador de depuración, debe usar versiones de depuración de la biblioteca estándar de C++ y la biblioteca en tiempo de ejecución de C para compilar el programa. Para obtener más información, vea Características de la biblioteca CRT. Para obtener información sobre cómo usar iteradores comprobados, vea Iteradores comprobados.

El estándar de C++ describe cómo las funciones miembro pueden provocar que los iteradores de un contenedor se conviertan en no válidos. Dos ejemplos son:

  • Borrar un elemento de un contenedor hace que los iteradores del elemento sean no válidos.

  • Aumentar el tamaño de un vector mediante inserción causa que los iteradores de vector no sean válidos.

Iteradores no válidos

Si compila este programa de ejemplo en modo de depuración, en tiempo de ejecución se valida y finaliza.

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

Uso de _ITERATOR_DEBUG_LEVEL

Puede usar la macro de preprocesador _ITERATOR_DEBUG_LEVEL para desactivar la característica de depuración de iteradores en una compilación de depuración. Este programa no valida, pero aún desencadena un comportamiento indefinido.

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

Iteradores sin inicializar

También se produce una aserción si intenta usar un iterador antes de que se inicialice, tal como se muestra aquí:

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

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

Iteradores incompatibles

En el ejemplo de código siguiente se produce una aserción porque los dos iteradores del algoritmo for_each son incompatibles. Comprobación de algoritmos para determinar si los iteradores que se les suministran hacen referencia al mismo contenedor.

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

Tenga en cuenta que este ejemplo usa la expresión lambda [] (int& elem) { elem *= 2; } en lugar de un functor. Aunque esta opción no tiene ningún efecto en el fallo de aserción (un functor parecido provocaría el mismo error) las lambdas son una manera de escribir un bloque corto de código. Para más información sobre las expresiones lambda, consulte Expresiones lambda.

Iteradores que salen del ámbito

Las comprobaciones de iteradores de depuración también provocan que una variable de iterador que se declara en un bucle for esté fuera de ámbito cuando el ámbito de bucle for finaliza.

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

Destructores para iteradores de depuración

Los iteradores de depuración tienen destructores no triviales. Si un destructor no se ejecuta, pero se libera la memoria del objeto, pueden producirse infracciones de acceso y daños en los datos. Considere este ejemplo:

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

Consulte también

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