Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Библиотека времени выполнения Visual C++ обнаруживает некорректное использование итераторов, выполняет проверочное утверждение и отображает диалоговое окно во время выполнения. Чтобы включить поддержку отладочных итераторов, необходимо использовать отладочные версии стандартной библиотеки C++ и библиотеки времени выполнения C для компиляции программы. Дополнительные сведения см. в разделе Функции библиотеки CRT. Сведения об использовании проверяемых итераторов см. в разделе Проверяемые итераторы.
В стандарте языка C++ описано, как функции-члены могут сделать недействительными итераторы в контейнер. Ниже приведены два примера:
В случае удаления элемента из контейнера итераторы в этот элемент становятся недействительными.
Увеличение размера вектора с помощью операции выталкивания или вставки делает недействительными итераторы в
vector.
Недопустимые итераторы
При компиляции данного примера программы в режиме отладки во время выполнения она выполняет подтверждение и прекращает выполнение.
// 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
}
Использование _ITERATOR_DEBUG_LEVEL
Для выключения функции отладки итераторов в отладочной сборке можно использовать макрос препроцессора _ITERATOR_DEBUG_LEVEL. Эта программа не утверждает, но по-прежнему запускает неопределенное поведение.
// 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
Неинициализированные итераторы
Утверждение также возникает при попытке использовать итератор перед инициализацией, как показано ниже:
// iterator_debugging_2.cpp
// compile by using: /EHsc /MDd
#include <string>
using namespace std;
int main() {
string::iterator i1, i2;
if (i1 == i2)
;
}
Несовместимые итераторы
Следующий пример кода вызывает проверочное утверждение, так как два итератора для алгоритма for_each несовместимы. Алгоритмы пытаются проверить, ссылаются ли предоставляемые в них итераторы на один и тот же контейнер.
// 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; } );
}
Обратите внимание, что в примере используется лямбда-выражение [] (int& elem) { elem *= 2; }, а не функция. Хотя этот выбор не имеет никакого отношения к сбою утверждения , аналогичный functor приведет к тому же сбою, лямбда-лямбда-код является способом записи короткого блока кода. Дополнительные сведения о лямбда-выражениях см. в разделе Лямбда-выражения.
Итераторы выходят из области
Проверки отладочных итераторов также приводят к выходу за пределы области переменной-итератора, которая объявлена в цикле for, когда область цикла for заканчивается.
// 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
}
Деструкторы для отладочных итераторов
Отладочные итераторы имеют нетривиальные деструкторы. Если деструктор не выполняется, но память объекта освобождается, могут возникнуть нарушения доступа и повреждение данных. Рассмотрим следующий пример:
// 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
}