C++ Assert tekshiruvlari
C++ da tasdiqlash - bu ifoda true bo'lishi kerakligini ta'kidlash yoki tasdiqlash uchun ishlatiladigan operator.
Agar xato bo'lmasa, sodir bo'lmaydigan sharoitlarni tekshirish uchun foydalaniladi. Shunday qilib, u nosozliklarni tuzatish vositasi sifatida ishlatiladi, chunki tasdiqlash false ga aylanganda dasturni tugatadi.
Misol uchun, agar biz bo'sh bo'lmagan vektor sonlarining o'rtacha qiymatini hisoblamoqchi bo'lsak, u holda tasdiq
nums.size() > 0
dasturda xatolik bo'lmasa, rost bo'lishi kerak.
C++ da biz cassert sarlavha faylida aniqlangan assert preprotsessor makrosidan foydalanib tasdiqlashdan foydalanishimiz mumkin.
#include <cassert>
Ushbu faylni import qilgandan so'ng, biz quyidagi sintaksis yordamida tasdiqlashni yaratishimiz mumkin:
assert(expression);
Bu erda, agar expression ga baholasa
#include <iostream>
#include <cassert>
using namespace std;
int main() {
int even_num = 3;
// juft_num qiymati juft bo'lishi kerakligini tasdiqlaydi
assert((even_num % 2 == 0));
return 0;
}
Chiqish
Assertion `(even_num % 2 == 0)' failed.
Aborted
Yuqoridagi misolda biz juft_num qiymati juft bo'lishi kerakligini tasdiqlash uchun assert makrosidan foydalanganmiz.
assert(even_num % 2 == 0);
juft_num qiymati 3 bo'lganligi sababli, hatto num % 2 == 0 tasdiqlovi bajarilmaydi. Natijada dastur tugaydi va xato xabari chop etiladi.
Lekin juft_numni 2 ga o'zgartirsak, dastur xatosiz ishlaydi.
[!NOTE] C++
assertmakrosi maxsus xato xabarlari uchun parametrni taqdim etmaydi. Ammo vergul operatori yordamida xato tavsifini qo'shishimiz mumkin.assert(("The number should be even", even_num % 2 == 0));Bu xato xabarini quyidagicha beradi:Assertion("Raqam juft bo'lishi kerak", juft_num % 2 == 0)' bajarilmadi`
Tasdiqlar xato bo'lmasa, sodir bo'lmasligi kerak bo'lgan shartlarni tekshirish uchun ishlatiladi. Shunday qilib, ular nosozliklarni tuzatish vositasi sifatida ishlatiladi.
Shuning uchun, biz ilovani chiqarishdan oldin tasdiqlarni olib tashlashimiz kerak, chunki chiqarilgan tuzilma funktsional bo'lishi kerak va hech qachon tasdiqni ishga tushirmasligi kerak.
Tasdiqlarni o'chirishning usullaridan biri disk raskadrovka tugallangandan so'ng kodda tasdiqlash makrosini qidirish va uni qo'lda olib tashlashdir.
NDEBUG makrosidan foydalanib, uni o'chirib qo'yish yaxshiroq yondashuvdir. Ushbu makro global miqyosdagi barcha tasdiqlarni e'tiborsiz qoldiradi. Biz ushbu makrosni cassert sarlavha faylini kiritishdan oldin #define direktivasi yordamida amalga oshirishimiz mumkin.
Shunday qilib, biz disk raskadrovka bilan yakunlanganimizda va tasdiqlashlar kerak bo'lmasa, biz quyidagi kodni qo'shishimiz mumkin.
#define NDEBUG
#include <cassert>
[!NOTE] Bir nechta faylga ega bo'lgan kattaroq loyiha uchun
NDEBUGkompilyator buyruq qatori opsiyalari yoki IDE sozlamalari orqali o'rnatilishi mumkin.
assert makrosi ish vaqtini tasdiqlash uchun ishlatiladi. Bundan farqli o'laroq, static_assert kompilyatsiya vaqtida tasdiqlash uchun ishlatiladi.
static_assert sintaksisi quyidagicha
static_assert(const_boolean_expression, message);
Bu yerga,
-const_boolean_expression - kompilyatsiya vaqtida ma'lum bo'lgan ifoda
-message - tasdiqlash muvaffaqiyatsiz bo'lsa ko'rsatadigan xabar
static_assert kalit so'z bo'lgani uchun biz hech qanday sarlavha faylini kiritishimiz shart emas.
#include <iostream>
using namespace std;
int main() {
static_assert(sizeof(int) >= 4, "Size of integer must be greater than or equal to 4 bytes");
return 0;
}
Yuqoridagi misolda biz statik tasdiqlardan foydalandik, shunda kod ishlayotgan platformada butun sonning o'lchami kamida 4 bayt bo'lishi kerak.
Ma'lumotlar turlarining o'lchami platformalarda farq qilishi mumkinligi sababli, kompilyatsiya vaqtida tasdiqlash uchun statik tasdiqlashdan foydalanishimiz mumkin.
Ish vaqtida bajariladigan assert dan farqli o'laroq, agar static_assert bajarilmasa, dastur kompilyatsiya qila olmaydi.
Bu erda, agar dasturni eski tizimda (16 bit) ishga tushirsak, sizeof(int) 2 bayt bo'lgani uchun tasdiqlash muvaffaqiyatsiz tugadi.
#include <iostream>
using namespace std;
template <class T, int size>
class Container {
static_assert(size > 0, "The size of container cannot be less than 1");
T items[size];
};
int main() {
Container<int, 0> st;
return 0;
}
Chiqish
error: static assertion failed: The size of container cannot be less than 1
Yuqoridagi misolda biz generic class dagi massiv o'lchami 0 dan katta bo'lishini ta'minlash uchun statik tasdiqdan foydalandik.
Bu erda biz Container sinfining ob'ektini yaratdik:
Container <int, 0> st;
O'lcham qiymati 0 bo'lganligi sababli, kompilyatsiya statik tasdiqlash muvaffaqiyatsiz xabari bilan bajarilmaydi.
Bu dasturni ishga tushirishga harakat qilganimizda bajarilmaydigan kodlar. Urib bo'lmaydigan kodlar haqiqatda mavjud emasligiga ishonch hosil qilish uchun tasdiqlardan foydalaning.
Keling, bir misol keltiraylik.
void unreachable_code_method() {
cout << "Reachable code";
return;
// Urib bo'lmaydigan kod
cout << "Unreachable code";
assert(false);
}
Keling, default holatisiz switch operatoriga misol keltiraylik.
switch (day_of_week) {
case 1:
cout << "It's Sunday!";
break;
case 2:
cout << "It's Monday!";
break;
case 3:
cout << "It's Tuesday!";
break;
case 4:
cout << "It's Wednesday!";
break;
case 5:
cout << "It's Thursday!";
break;
case 6:
cout << "It's Friday!";
break;
case 7:
cout << "It's Saturday!";
break;
Yuqoridagi switch operatori hafta kunlari faqat 1 dan 7 gacha bo'lishi mumkinligini ko'rsatadi. default ishi bo'lmasa, dasturchi bu holatlardan biri har doim bajarilishiga ishonadi.
Biroq, taxmin haqiqatda yolg'on bo'lgan ba'zi holatlar hali ko'rib chiqilmagan bo'lishi mumkin.
Ushbu taxmin default kalitiga etib bormaganligiga ishonch hosil qilish uchun tasdiqlash yordamida tekshirilishi kerak.
default:
assert(("An Invalid Day", false));
Agar haftaning_kunida 1 - 7 dan boshqa qiymat bo'lsa, tasdiqlash xatosi yuzaga keladi.
Ko'pgina dasturchilar o'zlarining asosiy taxminlarini hujjatlashtirish uchun sharhlardan foydalanadilar. Keling, bir misol keltiraylik.
if (i % 2 == 0) {
...
}
else { // Biz bilamiz (i % 2 == 1)
...
}
Buning o'rniga tasdiqlardan foydalaning.
Dastur o'sib ulg'aygan sari izohlar eskirgan va sinxronlashtirilmagan bo'lishi mumkin. Biroq, biz assert makrosini yangilashga majbur bo'lamiz; aks holda, ular amaldagi shartlar uchun ham muvaffaqiyatsiz bo'lishi mumkin.
if (i % 2 == 0) {
...
}
else {
assert(i % 2 == 1);
...
}
Umumiy funksiyalardagi argumentlar foydalanuvchi tomonidan taqdim etilishi mumkin.
Shunday qilib, agar ushbu dalillarni tekshirish uchun tasdiqlash ishlatilsa, shartlar muvaffaqiyatsiz bo'lishi va tasdiqlash xatosiga olib kelishi mumkin.
Tasdiqlashlardan foydalanish o'rniga, u tegishli ish vaqti istisnolariga olib kelsin va bu istisnolarni boshqaring.
Yon ta'sirga olib keladigan usullarni chaqirmang yoki istisnolarni baholamang. Masalan,
int n = 5;
// nojo'ya ta'sirlar bilan tasdiqlanish
// Bu erda tasdiqlash "n" ni kamaytiradi va agar n juft bo'lsa, tasdiqlaydi
assert(--n && n % 2 == 0);
Yuqoridagi misolda --n && n % 2 == 0 operatori yon ta'sirga ega, ya'ni u n o'zgaruvchining qiymatini o'zgartiradi. Bundan tashqari, tasdiqlash makrosi faqat tasdiqlash yoqilgan bo'lsa ishlaydi.
Ammo agar biz NDEBUG makrosidan foydalangan holda tasdiqlarni o'chirib qo'ygan bo'lsak, yuqoridagi dekrement amali hech qachon baholanmaydi, shuning uchun kodda keyinroq n ga havola qilingan bo'lsa, butun kodga ta'sir qiladi.
assert makrosida yon ta'sirga ega bo'lgan iboralarni baholash o'rniga, biz uni quyidagicha yozishimiz mumkin.
int n = 5;
// kamaytirish n
--n;
// nojo'ya ta'sirlarsiz tasdiq
// Bu erda tasdiq n juft bo'lsa, tasdiqlaydi
assert(n % 2 == 0);
Bu tasdiq yoqilgan yoki oʻchirilgan boʻlsa ham, n qiymati bir xil boʻlishini taʼminlaydi.