Compatibilidad de los iteradores de depuración

 

Para obtener la documentación más reciente de Visual Studio 2017 RC, consulte Documentación de Visual Studio 2017 RC.

La biblioteca en tiempo de ejecución de Visual C++ detecta uso incorrecto de iterador, y aserciones y muestra un cuadro de diálogo en tiempo de ejecución. Para habilitar la compatibilidad de iterador de depuración, debe utilizar una versión de depuración de 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, vea Iteradores activados.

El estándar de C++ describe cómo las funciones miembro pueden hacer iteradores un contenedor para volverse no válidas. Dos ejemplos son:

  • Borrar un elemento de un contenedor hace iteradores al elemento dejen de ser válido.

  • Aumentar el tamaño de vector (inserción o inserción) hace iteradores en vector dejen de ser válido.

Si compila el programa siguiente en modo de depuración, en tiempo de ejecución validar y finalizará.

/* compile with /EHsc /MDd */  
#include <vector>  
#include <iostream>  
  
int main() {  
   std::vector<int> v ;  
  
   v.push_back(10);  
   v.push_back(15);  
   v.push_back(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  
}  
  

Puede utilizar el símbolo _HAS_ITERATOR_DEBUGGING para desactivar la característica de depuración de iterador en una compilación de depuración. El siguiente programa no validar, pero todavía desencadena un comportamiento indefinido.

System_CAPS_ICON_important.jpg Importante

Uso _ITERATOR_DEBUG_LEVEL de controlar _HAS_ITERATOR_DEBUGGING. Para obtener más información, vea _ITERATOR_DEBUG_LEVEL.

// iterator_debugging.cpp  
// compile with: /EHsc /MDd  
#define _HAS_ITERATOR_DEBUGGING 0  
#include <vector>  
#include <iostream>  
  
int main() {  
   std::vector<int> v ;  
  
   v.push_back(10);  
   v.push_back(15);  
   v.push_back(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

Validar también aparece si intenta utilizar un iterador antes de inicializarse, como se muestra aquí:

/* compile with /EHsc /MDd */  
#include <string>  
using namespace std;  
int main() {  
   string::iterator i1, i2;  
   if (i1 == i2)  
      ;  
}  

El ejemplo de código siguiente se genera una aserción porque los dos iteradores del algoritmo de for_each son incompatibles. Comprobación de los algoritmos para determinar si los iteradores que se proporcionan a ellos hacen referencia al mismo contenedor.

/* compile with /EHsc /MDd */  
#include <algorithm>  
#include <vector>  
using namespace std;  
  
int main()  
{  
    vector<int> v1;  
    vector<int> v2;  
  
    v1.push_back(10);  
    v1.push_back(20);  
  
    v2.push_back(10);  
    v2.push_back(20);  
  
    // The next line will assert because v1 and v2 are  
    // incompatible.  
    for_each(v1.begin(), v2.end(), [] (int& elem) { elem *= 2; } );  
}  

Observe que este ejemplo utiliza la expresión lambda [] (int& elem) { elem *= 2; } en lugar de un functor. Aunque esta opción tiene ningún efecto en el error - uno validar que el functor similar produciría el mismo error - lambdas es una manera muy útil de lograr compacto las tareas del objeto. Para obtener más información sobre las expresiones lambda, vea Expresiones lambda.

Depurar el iterador que comprueba también genera una variable de iterador que se declara en un bucle de for que está fuera de ámbito cuando el ámbito del bucle de for finaliza.

// debug_iterator.cpp  
// compile with: /EHsc /MDd  
#include <vector>  
#include <iostream>  
int main() {  
   std::vector<int> v ;  
  
   v.push_back(10);  
   v.push_back(15);  
   v.push_back(20);  
  
   for (std::vector<int>::iterator i = v.begin() ; i != v.end(); ++i)  
   ;  
   --i;   // C2065  
}  

Los iteradores de depuración tienen destructores no triviales. Si el destructor no se ejecuta, por cualquier razón, las infracciones de acceso y daños en los datos se pueden producir. Considere este ejemplo:

/* compile with: /EHsc /MDd */  
#include <vector>  
struct base {  
   // 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  
}  

Información general de STL

Mostrar: