Podpora ladění iterátorů

Knihovna runtime Visual C++ detekuje nesprávné použití iterátoru a v době běhu zobrazí dialogové okno. Pokud chcete povolit podporu iterátoru ladění, musíte ke kompilaci programu použít ladicí verze standardní knihovny C++ a knihovny modulu C Runtime Library. Další informace naleznete v tématu Funkce knihovny CRT. Informace o použití kontrolovaných iterátorů naleznete v tématu Zaškrtnuté iterátory.

Standard jazyka C++ popisuje, jak můžou členské funkce způsobit, že iterátory kontejneru přestanou být neplatné. Mezi dva příklady patří:

  • Vymazání elementu z kontejneru způsobí, že iterátory prvku se stanou neplatnými.

  • Zvětšením velikosti vektoru pomocí vložení nebo vložení dojde k neplatnému iterátoruvector.

Neplatné iterátory

Pokud tento ukázkový program zkompilujete v režimu ladění, v době běhu ho vytvrdí a ukončí.

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

Použití _ITERATOR_DEBUG_LEVEL

Pomocí makra preprocesoru _ITERATOR_DEBUG_LEVEL můžete vypnout funkci ladění iterátoru v sestavení ladění. Tento program neprovádí, ale přesto aktivuje nedefinované chování.

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

Neinicializované iterátory

K kontrolnímu výrazu dojde také v případě, že se před inicializaci pokusíte použít iterátor, jak je znázorněno tady:

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

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

Nekompatibilní iterátory

Následující příklad kódu způsobí kontrolní výraz, protože dva iterátory algoritmu for_each nejsou kompatibilní. Algoritmy kontrolují, jestli iterátory zadané pro ně odkazují na stejný kontejner.

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

Všimněte si, že tento příklad používá výraz [] (int& elem) { elem *= 2; } lambda místo functoru. I když tato volba nemá žádný vliv na selhání kontrolního výrazu – podobný functor by způsobil stejnou chybu – lambda představují způsob, jak napsat krátký blok kódu. Další informace o výrazech lambda najdete v tématu Výrazy lambda.

Iterátory, které vyjdou mimo rozsah

Kontroly iterátoru ladění také způsobí, že proměnná iterátoru deklarovaná ve for smyčce bude mimo rozsah, když for obor smyčky skončí.

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

Destruktory pro iterátory ladění

Ladicí iterátory mají ne triviální destruktory. Pokud se destruktor nespustí, ale uvolní se paměť objektu, může dojít k narušení přístupu a poškození dat. Podívejte se na tento příklad:

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

Viz také

Standardní knihovna C++ – přehled