PVS-Studio, seperti penganalisa kode statis lainnya, sering menghasilkan positif palsu. Tapi jangan buru-buru menganggap tanggapan aneh itu salah. Ini adalah cerita pendek tentang bagaimana PVS-Studio kembali menjadi lebih memperhatikan beberapa orang.
Pengguna menulis untuk mendukung kami, mengklaim bahwa penganalisa segera menghasilkan empat positif palsu per baris kode. Surat itu, yang ditulis dalam dukungan, awalnya datang ke Yevgeny Ryzhkov, yang, setelah membacanya dengan lancar dan tidak memperhatikan umpan balik yang aneh, segera mengirimkannya ke pengembang utama Svyatoslav Razmyslov. Eugene tidak mengintip ke dalam kode, jadi akan adil untuk menghitungnya hanya untuk setengah programmer :).
Svyatoslav membaca surat itu dan meragukan bahwa penganalisa itu bisa sangat keliru. Karena itu, dia datang kepada saya untuk konsultasi. Svyatoslav memiliki harapan bahwa mata saya telah diatur dan saya akan melihat sesuatu yang memberi tahu saya mengapa penganalisa mengeluarkan semua pesan aneh ini. Sayangnya, saya hanya mengkonfirmasi bahwa pesannya sangat aneh dan tidak seharusnya. Namun, apa alasan terjadinya mereka, saya tidak bisa perhatikan. Diputuskan untuk membuka tugas di bugtracker dan mulai memahami apa yang salah.
Dan hanya ketika Svyatoslav mulai membuat contoh-contoh sintetis untuk menjelaskan secara rinci masalah dalam penelusur bug, wawasan muncul padanya. Sekarang mari kita lihat apakah Anda dapat dengan cepat menemukan alasan mengapa penganalisa menampilkan 4 pesan.
Ini adalah teks surat itu, diterbitkan dengan izin dari penulis. Dan gambar penjelasan yang dilampirkan pada surat itu.
Peringatan V560 di sini semuanya salah. Berjalan dengan versi PVS-Studio terbaru untuk penggunaan pribadi. Pada dasarnya, pernyataan "JIKA" benar. Yang luar dilakukan untuk kecepatan - yang dalam masih dibutuhkan dan yang tidak selalu benar atau salah.
Sekarang, pembaca yang budiman, waktu Anda untuk menguji diri sendiri! Lihat kesalahannya?
Waktu Anda untuk penuh perhatian. Dan unicorn akan menunggu sebentar.
Setelah bagian pengantar artikel, kemungkinan besar banyak menemukan kesalahan. Ketika dikonfigurasi untuk menemukan kesalahan, itu ditemukan. Jauh lebih sulit untuk melihat kesalahan setelah membaca surat itu, yang disebut “false positive” :).
Sekarang penjelasan bagi mereka yang terlalu malas untuk mencari bug. Pertimbangkan kondisinya lagi:
if (!((ch >= 0x0FF10) && (ch <= 0x0FF19)) || ((ch >= 0x0FF21) && (ch <= 0x0FF3A)) || ((ch >= 0x0FF41) && (ch <= 0x0FF5A)))
Penulis kode berencana untuk memverifikasi bahwa karakter tidak termasuk dalam salah satu dari tiga rentang.
Kesalahannya adalah bahwa operator NOT logis (!) Berlaku hanya untuk subekspresi pertama.
Jika kondisinya terpenuhi:
!((ch >= 0x0FF10) && (ch <= 0x0FF19))
maka evaluasi ekspresi terganggu sesuai dengan
evaluasi hubung singkat . Jika kondisi tidak terpenuhi, maka nilai variabel
ch terletak pada kisaran [0xFF10..0xFF19]. Dengan demikian, empat perbandingan lebih lanjut tidak masuk akal. Semuanya akan salah atau benar.
Sekali lagi. Lihat, jika
ch terletak di kisaran
[0xFF10..0xFF19] dan perhitungan berlanjut, maka:
- ch> = 0x0FF21 - selalu salah
- ch <= 0x0FF3A - selalu benar
- ch> = 0x0FF41 - selalu salah
- ch <= 0x0FF5A - selalu benar
Inilah yang diperingatkan oleh penganalisa PVS-Studio.
Jadi, penganalisa statis ternyata lebih perhatian daripada pengguna dan dua setengah programmer dari tim kami.
Untuk memperbaiki situasi, Anda perlu menambahkan tanda kurung:
if (!(((ch >= 0x0FF10) && (ch <= 0x0FF19)) || ((ch >= 0x0FF21) && (ch <= 0x0FF3A)) || ((ch >= 0x0FF41) && (ch <= 0x0FF5A))))
Atau tulis ulang kondisinya:
if (((ch < 0x0FF10) || (ch > 0x0FF19)) && ((ch < 0x0FF21) || (ch > 0x0FF3A)) && ((ch < 0x0FF41) || (ch > 0x0FF5A)))
Namun, saya tidak bisa merekomendasikan menggunakan salah satu opsi ini. Saya akan menulis ini untuk mempermudah membaca kode:
const bool isLetterOrDigit = (ch >= 0x0FF10 && ch <= 0x0FF19)
Perhatikan bahwa saya menghapus beberapa tanda kurung. Seperti yang baru saja kita lihat, sejumlah besar kurung tidak membantu untuk menghindari kesalahan sama sekali. Kurung harus membuatnya lebih mudah untuk membaca kode, tidak lebih rumit. Pemrogram mengingat dengan baik bahwa prioritas perbandingan = <, => lebih tinggi daripada operator &&. Karena itu, tanda kurung tidak diperlukan di sini. Tetapi jika Anda bertanya prioritas mana yang && atau ||, banyak yang akan bingung. Karenanya, untuk menentukan urutan perhitungan &&, || kurung lebih baik untuk diletakkan.
Mengapa lebih baik menulis || di awal saya jelaskan di artikel "
Masalah utama pemrograman, refactoring dan semua itu " (lihat bab: Sejajarkan jenis kode yang sama dengan "tabel").
Terima kasih atas perhatiannya. Unduh dan mulai gunakan
PVS-Studio . Ini akan membantu mengidentifikasi banyak kesalahan dan kerentanan potensial pada tahap paling awal.

Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Andrey Karpov.
Bagaimana PVS-Studio Terbukti Lebih Penuh Perhatian Daripada Tiga Setengah Programer .