Lanjutan: mengecewakan opini tentang penganalisis kode statis

gambar1.png


Rencananya setelah menulis artikel "Sangat memalukan untuk pendapat tentang penganalisis kode statis", kami akan berbicara dan dengan tenang melepaskan topik tersebut. Namun tak disangka, artikel ini menimbulkan tanggapan yang heboh. Sayangnya, diskusi berjalan salah, dan sekarang kami akan melakukan upaya kedua untuk menjelaskan visi kami tentang situasi tersebut.



Analogi anekdot



Jadi, semuanya dimulai dengan artikel " Sangat memalukan untuk opini tentang penganalisis kode statis ". Dia mulai aktif membahas beberapa sumber dan diskusi ini sangat mirip dengan anekdot lama berikut.
Kami membeli gergaji mesin Jepang untuk beberapa penebang kayu Siberia yang keras.

Para penebang kayu berkumpul dalam lingkaran dan memutuskan untuk mengujinya.

Mereka membawanya masuk, memberinya sebatang pohon.

"Ritsleting," kata gergaji Jepang itu.

"Oh, sial ..." - kata para penebang pohon.

Mereka memberinya pohon yang lebih tebal. "Vzh-g-zhik!" - kata gergaji.

"Wow, sial!" - kata para penebang pohon.

Mereka menyelipkan pohon cedar tebal ke tubuhnya. "VZH-ZH-ZH-ZH-ZH-ZH-ZHIK !!!" - kata gergaji.

"Wow, sial !!" - kata para penebang pohon.

Mereka memberinya sepotong besi. "RETAK!" - kata gergaji.

"Ya, sial !!!" - Kata penebang Stern Siberia mencela! Dan mereka pergi untuk menebang hutan dengan kapak ...
Cerita satu lawan satu. Orang-orang melihat kode:



if (A[0] == 0)
{
  X = Y;
  if (A[0] == 0)
    ....
}


Dan mereka mulai menciptakan situasi yang mungkin dapat dibenarkan, yang berarti peringatan penganalisis PVS-Studio adalah positif palsu. Penalaran masuk ke dalam mata kuliah tentang perubahan memori antara dua cek, yang timbul dari:



  • pekerjaan aliran paralel;
  • penangan sinyal / interupsi;
  • variabel X adalah referensi ke elemen A [0] ;
  • perangkat keras, seperti menjalankan operasi DMA;
  • dll.


Dan setelah membahas bahwa tidak semua situasi yang dapat dipahami oleh penganalisis, mereka pergi untuk menebang hutan dengan kapak. Artinya, kami menemukan alasan mengapa memungkinkan untuk terus tidak menggunakan penganalisis kode statis dalam pekerjaan kami.



Visi kami tentang situasi



Pendekatan ini kontraproduktif. Alat yang tidak sempurna mungkin berguna, dan penggunaannya layak secara ekonomi.



Ya, penganalisis statis apa pun menghasilkan positif palsu. Dan tidak ada yang bisa dilakukan tentang itu. Namun, kemalangan ini sangat dibesar-besarkan. Dalam praktiknya, penganalisis statis dapat dikonfigurasi dan digunakan dalam berbagai cara untuk menekan dan bekerja dengan positif palsu (lihat 1 , 2 , 3 , 4 ). Plus, di sini pantas untuk mengingat artikel " Positif palsu adalah musuh kita, tetapi mungkin masih teman Anda ".



Namun, ini pun bukanlah hal yang utama. Tidak masuk akal untuk mempertimbangkan kasus khusus kode eksotis sama sekali!Dapatkah Anda mengacaukan penganalisis dengan kode yang rumit? Ya kamu bisa. Namun, untuk satu kasus seperti itu, akan ada ratusan pemicu penganalisis yang berguna. Banyak kesalahan dapat ditemukan dan diperbaiki pada tahap yang sangat awal. Dan satu atau dua alarm palsu dapat ditekan dengan aman dan tidak lagi memperhatikannya.



Dan lagi PVS-Studio benar



Disini artikel bisa selesai. Namun, beberapa orang mungkin menganggap bagian sebelumnya bukan pertimbangan rasional, tetapi mencoba menyembunyikan kelemahan dan kekurangan alat PVS-Studio. Jadi, Anda harus melanjutkan.



Pertimbangkan kode kompilasi konkret yang mencakup deklarasi variabel:



void SetSynchronizeVar(int *);

int foo()
{
    int flag = 0;
    SetSynchronizeVar(&flag);

    int X, Y = 1;

    if (flag == 0)
    {
        X = Y;
        if (flag == 0)
            return 1;
    }
    return 2;
}


Penganalisis PVS-Studio secara wajar mengeluarkan peringatan: V547 Expression 'flag == 0' selalu benar.



Dan penganalisisnya benar. Jika seseorang mulai mengomel bahwa variabel dapat berubah di utas lain, di penangan sinyal, dan seterusnya, maka dia sama sekali tidak memahami bahasa C dan C ++. Anda tidak bisa menulis seperti itu.



Untuk tujuan pengoptimalan, kompilator memiliki hak untuk membuang pemeriksaan kedua dan akan sepenuhnya benar. Dari sudut pandang bahasa, variabel tidak bisa berubah. Perubahan latar belakangnya tidak lebih dari perilaku yang tidak ditentukan.



Agar pemeriksaan tetap di tempatnya, variabel harus dinyatakan mudah menguap :



void SetSynchronizeVar(volatile int *);

int foo()
{
    volatile int flag = 0;
    SetSynchronizeVar(&flag);
    ....
}


Penganalisis PVS-Studio mengetahui hal ini dan tidak lagi mengeluarkan peringatan untuk kode semacam itu .



Di sini kita kembali ke apa yang telah dibahas di artikel pertama . Tidak ada masalah. Namun ada kritik atau kesalahpahaman mengapa penganalisis berhak mengeluarkan peringatan.



Catatan untuk pembaca yang paling teliti



Beberapa pembaca mungkin kembali ke contoh sintetis dari artikel pertama:



char get();
int foo(char *p, bool arg)
{
    if (p[1] == 1)
    {
        if (arg)
            p[0] = get();
        if (p[1] == 1)          // Warning
            return 1;
    }
    // ....
    return 3;
}


Dan tambahkan volatile :



char get();
int foo(volatile char *p, bool arg)
{
    if (p[1] == 1)
    {
        if (arg)
            p[0] = get();
        if (p[1] == 1)          // Warning :-(
            return 1;
    }
    // ....
    return 3;
}


Setelah itu, dapat dikatakan bahwa penganalisis masih mengeluarkan peringatan V547 Expression 'p [1] == 1' selalu benar.



Hore, akhirnya terbukti bahwa penganalisisnya masih salah :). Ini adalah positif palsu!



Seperti yang Anda lihat, kami tidak menyembunyikan kekurangan apa pun. Saat mengurai aliran data untuk elemen array, volatil naas ini hilang. Cacat telah ditemukan dan diperbaiki. Perbaikan akan tersedia di versi penganalisis berikutnya. Tidak akan ada kesalahan positif.



Mengapa bug ini tidak diidentifikasi sebelumnya? Karena sebenarnya, ini adalah kode yang tidak nyata yang tidak ditemukan dalam proyek nyata. Sebenarnya, kami belum menemukan kode seperti itu sejauh ini, meskipun kami telah memeriksa banyak proyek sumber terbuka .



Mengapa kodenya tidak realistis? Pertama, dalam praktiknya, akan ada semacam pengaturan waktu atau fungsi penundaan antara kedua pemeriksaan. Kedua, tidak ada orang waras, kecuali benar-benar diperlukan, membuat array yang terdiri dari elemen volatil. Bekerja dengan array seperti itu adalah penurunan kinerja yang sangat besar.



Mari kita rangkum. Sangat mudah untuk membuat contoh di mana parser gagal. Tetapi dari sudut pandang praktis, kekurangan yang teridentifikasi secara praktis tidak mempengaruhi kualitas analisis kode dan jumlah kesalahan nyata yang terdeteksi. Bagaimanapun, kode aplikasi nyata hanyalah kode yang dapat dimengerti oleh penganalisis dan orang pada saat yang sama, dan bukan rebus atau teka-teki. Jika kodenya adalah teka-teki, maka tidak ada waktu untuk penganalisis :).



Terima kasih atas perhatian Anda.





Tautan tambahan









Jika Anda ingin berbagi artikel ini dengan audiens berbahasa Inggris, silakan gunakan tautan terjemahan: Andrey Karpov. Bagian 2: Pendapat yang Mengesalkan tentang Analisis Statis .



All Articles