Belirsiz davranış (Undefined Behavior, UB) — dilin standartlarının programın davranışını tanımlamadığı durumdur. Derleyici programla her şeyi yapabilir: program çökebilir, yanlış sonuç verebilir ya da 'çalışabilir'. UB, dizi sınırlarının dışına çıkma, null işaretçiyi çözme gibi hatalardan kaynaklanır.
int arr[5]; arr[10] = 42; // UB: dizi sınırları dışında int* p = nullptr; *p = 1; // UB: 0'ı çözme
UB'den kaçınmak için standartlara uyulmalı, modern araçlar kullanılmalı (ASan, UBSan, valgrind), ham işaretçilerin kullanılmasından kaçınılmalı ve güvenli kod yazılmalıdır.
Bir programın bir tarafında UB meydana gelirse, bu tamamen bağımsız bir kod parçasını etkileyebilir mi?
Evet! Derleyici optimizasyon sırasında, UB'nin meydana geldiğini fark ederse beklenmedik dönüşümler yapabilir.
void foo(int* p) { if (p == nullptr) return; *p = 5; // Eğer p null değilse, bu UB! Fakat derleyici p'nin her zaman geçerli olduğunu varsayıp kontrolleri kaldırabilir. }
Hikaye
Büyük bir şirketin sunucusunda, null işaretçinin çözülmesi nedeniyle zaman zaman rastgele süreç çöküşleri meydana geliyordu; bunları yeniden oluşturmak zordu: debug’da her şey çalışıyordu, ancak release’de çalışmıyordu.
Hikaye
32-bit'ten 64-bit'e kod taşırken, veri türleri karıştırıldı, int ile işaretçi arasında cast yapıldı. Bazı makinelerde çalıştı, diğerlerinde çöküşler ve garip artefaktlar ortaya çıktı.
Hikaye
İnternette, masum bir UB'nin (dizi sınırları dışına çıkma) tüm programın işleyişini bozduğu bir durum biliniyor: derleyici sadece dizi ile olan işlemleri değil, hatayla bağlantılı olmayan kod parçalarını da 'optimize' etti.