Aracılığıyla paylaş


Hata Ayıklama Yineleyicisi Desteği

Visual C++ çalışma zamanı kitaplığı yanlış yineleyici kullanımı algılar ve çalışma zamanında bir iletişim kutusu onaylar ve görüntüler. Hata ayıklama yineleyicisi desteğini etkinleştirmek için, programınızı derlemek için C++ Standart Kitaplığı ve C Çalışma Zamanı Kitaplığı'nın hata ayıklama sürümlerini kullanmanız gerekir. Daha fazla bilgi için bkz . CRT Kitaplığı Özellikleri. denetlenen yineleyicileri kullanma hakkında bilgi için bkz . İşaretli Yineleyiciler.

C++ standardı, üye işlevlerinin kapsayıcıda yineleyicilerin geçersiz olmasına nasıl neden olabileceğini açıklar. İki örnek:

  • Kapsayıcıdan bir öğenin silinmesi, öğede yineleyicilerin geçersiz olmasına neden olur.

  • Gönderme veya ekleme kullanarak vektör boyutunu artırmak, içine yineleyicilerin vector geçersiz olmasına neden olur.

Geçersiz yineleyiciler

Bu örnek programı hata ayıklama modunda derlerseniz, çalışma zamanında onaylanır ve sonlandırılır.

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

Bir hata ayıklama derlemesinde yineleyici hata ayıklama özelliğini kapatmak için önişlemci makro _ITERATOR_DEBUG_LEVEL kullanabilirsiniz. Bu program onaylamaz, ancak yine de tanımsız davranışı tetikler.

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

Başlatılmamış yineleyiciler

Burada gösterildiği gibi bir yineleyiciyi başlatılmadan önce kullanmayı denediğinizde de onay oluşur:

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

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

Uyumsuz yineleyiciler

Aşağıdaki kod örneği, for_each algoritmasının iki yineleyicisi uyumsuz olduğundan onaylama işlemine neden olur. Algoritmalar, kendilerine sağlanan yineleyicilerin aynı kapsayıcıya başvurup başvurmadığını denetler.

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

Bu örnekte functor yerine lambda ifadesi [] (int& elem) { elem *= 2; } kullanıldığına dikkat edin. Bu seçimin onay hatasıyla bir ilgisi olmasa da (benzer bir functor aynı hataya neden olabilir), lambdalar kısa bir kod bloğu yazmanın bir yoludur. Lambda ifadeleri hakkında daha fazla bilgi için bkz . Lambda ifadeleri.

Kapsam dışında olan yineleyiciler

Hata ayıklama yineleyici denetimleri, döngü kapsamı sona erdiğinde döngüde bildirilen bir for yineleyici değişkeninin for kapsam dışında olmasına da neden olur.

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

Hata ayıklama yineleyicileri için yıkıcılar

Hata ayıklama yineleyicileri önemsiz olmayan yıkıcılara sahiptir. Bir yıkıcı çalışmazsa ancak nesnenin belleği serbest kalırsa erişim ihlalleri ve veri bozulması oluşabilir. Bu örneği ele alalım:

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

Ayrıca bkz.

C++ Standart Kitaplığına Genel Bakış