Déboguez une prise en charge des itérateurs
La bibliothèque Runtime Visual C++ détecte l'utilisation incorrecte d'itérateur, et déclare et affiche une boîte de dialogue au moment de l'exécution.Pour activer le débogage en charge des itérateurs, vous devez utiliser une version debug de la bibliothèque Runtime c pour compiler votre programme.Pour plus d'informations, consultez Fonctionnalités de bibliothèque CRT.Pour plus d'informations sur l'utilisation des itérateurs, consultez Itérateurs vérifiés.
La norme C++ décrit comment les fonctions membres peuvent faire devenir des itérateurs à un conteneur non valides.Deux exemples sont :
Suppression d'un élément d'un conteneur fait devenir des itérateurs à l'élément non valides.
Augmenter la taille d' vecteur (transmission de type push ou insertion) fait devenir des itérateurs dans vector non valides.
Exemple
Si vous compilez le programme suivant en mode débogage lors de l'exécution, il affirmera et se terminera.
/* 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
}
Vous pouvez utiliser le symbole _HAS_ITERATOR_DEBUGGING pour désactiver la fonctionnalité de débogage itérateur dans une version debug.Le programme suivant ne déclare pas, mais déclenche toujours le comportement non défini.
Important
Utilisation _ITERATOR_DEBUG_LEVEL de contrôler _HAS_ITERATOR_DEBUGGING.Pour plus d'informations, consultez _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
}
Une assertion se produit également si vous essayez d'utiliser un itérateur avant d'être initialisé, comme indiqué ci-après :
/* compile with /EHsc /MDd */
#include <string>
using namespace std;
int main() {
string::iterator i1, i2;
if (i1 == i2)
;
}
L'exemple de code suivant crée une assertion parce que les deux itérateurs à l'algorithme d' for_each sont incompatibles.Les algorithmes contrôle pour déterminer si les itérateurs qui sont fournis à eux référencent le même conteneur.
/* 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; } );
}
Notez que cet exemple utilise l'expression lambda [] (int& elem) { elem *= 2; } au lieu d'un functor.Bien que ce choix a pas portant sur l'échec - d'assertion le functor que similaire provoquerait le même échec - expressions lambda sont très utile d'accomplir compact s'exécutent des tâches d'objet.Pour plus d'informations sur les expressions lambda, consultez Expressions lambda en C++.
Déboguez l'itérateur vérification également provoque une variable itérateur qui est déclarée dans une boucle d' for pour être hors de portée lorsque la portée de la boucle d' for termine.
// 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
}
Déboguez des itérateurs ont les destructeurs non triviaux.Si un destructeur ne fonctionne pas, pour quelque raison que ce soit, les violations d'accès et des données endommagées peuvent se produire.Considérez cet exemple :
/* 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
}