Freigeben über


Debug- Iteratorunterstützung

Die Visual C++-Laufzeitbibliothek erkennt falsche Iteratorverwendung und erläutert und zeigt ein Dialogfeld zur Laufzeit.Um Debug- Iteratorunterstützung zu aktivieren, müssen Sie eine Debugversion der Wechselstrom-Laufzeitbibliothek verwenden um das Programm zu kompilieren.Weitere Informationen finden Sie unter CRT-Bibliotheks-Funktionen.Informationen darüber, wie Iteratoren, finden Sie unter Überprüfte Iteratoren verwendet.

Im C++-Standard wird beschrieben, wie Memberfunktionen möglicherweise Iteratoren zu einem Container dazu, ungültig werden.Zwei Beispiele sind:

  • Das Löschen eines Elements von einem Container wird Iteratoren auf das Element, ungültig werden.

  • Durch Erhöhen der Größe von vector (Push oder Einfügen) bewirkt Iteratoren in vector, ungültig werden.

Beispiel

Wenn Sie das folgende Programm im Debugmodus kompilieren, zur Laufzeit erläutert und er beendet wird.

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

Sie können das Symbol _HAS_ITERATOR_DEBUGGING verwenden, um die Iteratordebuggingsfunktion in einem Debugbuild zu deaktivieren.Das folgende Programm erläutert, nicht aber dennoch markierte Trigger Verhalten Definition auf.

Wichtiger HinweisWichtig

Verwendung _ITERATOR_DEBUG_LEVEL, _HAS_ITERATOR_DEBUGGING zu steuern.Weitere Informationen finden Sie unter _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
}
  

Eine Assertion tritt auch auf, wenn Sie versuchen, einen Iterator wie dargestellt zu verwenden, bevor er initialisiert wird, hier:

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

Im folgenden Codebeispiel wird eine Assertion, da die beiden Iteratoren zum for_each Algorithmus nicht kompatibel sind.Algorithmen überprüfen, um zu bestimmen, ob die Iteratoren, die ihnen angegeben werden, den gleichen Container verweisen.

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

Beachten Sie, dass dieses Beispiel den Lambda-Ausdruck [] (int& elem) { elem *= 2; } anstelle eines Feature-Elements verwendet.Obwohl diese Auswahl im Assertionsfehler-ein Beide Methoden können verwendet werden, den Ähnliches Funktionselement denselben Fehler-lambdas sind sehr nützlich, kompakte Funktionsobjektaufgaben zu erfüllen führen würde.Weitere Informationen zu Lambdaausdrücken finden Sie unter Lambda-Ausdrücke in C++.

Debuggen Sie den Iterator, der auch überprüft, verursacht eine Iteratorvariable, die in einer for Schleife deklariert wird, um außerhalb des Bereichs zu werden, wenn der for Schleifenbereich beendet.

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

Debug- Iteratoren haben nicht-triviale Destruktoren.Wenn ein Destruktor nicht, aus welchem Grund auch immer ausgeführt wird, treten möglicherweise Zugriffsverletzungen und Datenbeschädigungen auf.Betrachten Sie das folgende Beispiel:

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

Siehe auch

Referenz

C++-Standardbibliothek-Übersicht