Supporto iteratori di debug
La libreria di runtime di Visual C++ rileva l'utilizzo non corretto degli iteratori e le asserzioni e visualizzare una finestra di dialogo in fase di esecuzione.Per abilitare il supporto iteratori di debug, è necessario utilizzare una versione di debug della libreria di runtime c per compilare il programma.Per ulteriori informazioni, vedere Funzionalità della libreria CRT.Per informazioni su come utilizzare gli iteratori, vedere Iteratori verificati.
Lo standard C++ viene descritto come funzioni membro possono causare gli iteratori a un contenitore a diventare non validi.Due esempi sono:
Eliminazione dell'elemento da un contenitore che gli iteratori all'elemento a diventare non validi.
L'aumento delle dimensioni di vettore (push o inserimento) determina gli iteratori in vector a diventare non validi.
Esempio
Se si compila il programma in modalità di debug, in fase di esecuzione asserirà e terminerà.
/* 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
}
È possibile utilizzare il simbolo _HAS_ITERATOR_DEBUGGING disattivare la funzionalità di debug iteratori in una build di debug.Il seguente programma non asserisce, pur i trigger hanno un comportamento indefinito.
Importante |
---|
Utilizzo _ITERATOR_DEBUG_LEVEL controllare _HAS_ITERATOR_DEBUGGING.Per ulteriori informazioni, vedere _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
}
Un'asserzione si verifica se si tenta di utilizzare un iteratore prima che venga inizializzato, come illustrato di seguito:
/* compile with /EHsc /MDd */
#include <string>
using namespace std;
int main() {
string::iterator i1, i2;
if (i1 == i2)
;
}
Nell'esempio di codice viene un'asserzione poiché i due iteratori all'algoritmo di for_each sono incompatibili.Gli algoritmi controllano per determinare se gli iteratori forniti a esse siano facendo riferimento allo stesso contenitore.
/* 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; } );
}
Si noti che in questo esempio viene utilizzata l'espressione lambda [] (int& elem) { elem *= 2; } anziché un functor.Sebbene questa scelta sono rilevanti all'errore - un di asserzione il simile functor causerebbe lo stesso errore - lambda è una soluzione molto utile eseguire le attività compresse dell'oggetto funzione.Per ulteriori informazioni sulle espressioni lambda, vedere Espressioni lambda in C++.
Eseguire il debug dell'iteratore che controlla inoltre possibile causa una variabile di iteratore dichiarata in un ciclo di for all'ambito quando l'ambito del ciclo di for termina.
// 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
}
Gli iteratori di debug con distruttori complesse.Se un distruttore non funziona, per qualsiasiasi motivo, le violazioni di accesso e l'alterazione dei dati potrebbero verificarsi.Si consideri l'esempio seguente:
/* 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
}