Bagikan melalui


Peringatan C26430

Simbol tidak diuji untuk nullness pada semua jalur.

Pedoman Inti C++: F.23: Gunakan not_null<T> untuk menunjukkan bahwa "null" bukan nilai yang valid

Jika kode pernah memeriksa variabel pointer untuk null, kode harus melakukannya secara konsisten dan memvalidasi pointer di semua jalur. Terkadang pemeriksaan berlebihan untuk null masih lebih baik daripada kemungkinan crash keras di salah satu cabang yang rumit. Idealnya, kode tersebut harus direfaktor menjadi kurang kompleks (dengan membaginya menjadi beberapa fungsi), dan untuk mengandalkan penanda seperti gsl::not_null. Penanda ini memungkinkan kode untuk mengisolasi bagian algoritma yang dapat membuat asumsi aman tentang nilai pointer yang valid. Aturan TEST_ON_ALL_PATHS ini membantu menemukan tempat di mana pemeriksaan null tidak konsisten (artinya asumsi mungkin memerlukan peninjauan). Atau, ia menemukan bug aktual di mana nilai null potensial dapat melewati pemeriksaan null di beberapa jalur kode.

Keterangan

Aturan ini mengharapkan bahwa kode mendereferensikan variabel penunjuk sehingga pemeriksaan null (atau penerapan nilai non-null) akan dibenarkan. Jika tidak ada dereferensi, aturan akan ditangguhkan.

Implementasi saat ini hanya menangani pointer biasa (atau aliasnya) dan tidak mendeteksi penunjuk pintar, meskipun pemeriksaan null juga berlaku untuk penunjuk pintar.

Variabel ditandai sebagai diperiksa null saat digunakan dalam konteks berikut:

  • sebagai ekspresi simbol dalam kondisi cabang, misalnya, dalam if (p) { ... };
  • dalam operasi logis non-bitwise;
  • dalam operasi perbandingan di mana satu operand adalah ekspresi konstanta yang mengevaluasi ke nol.

Pemeriksaan null implisit diasumsikan ketika nilai pointer ditetapkan dari:

  • alokasi yang dilakukan dengan melempar operator new;
  • pointer yang diperoleh dari jenis yang ditandai dengan gsl::not_null.

Contoh

Pengujian yang tidak konsisten mengungkapkan kesalahan logika

void merge_states(const state *left, const state *right) // C26430
{
    if (*left && *right)
        converge(left, right);
    else
    {
        // ...
        if (!left && !right)                            // Logic error!
            discard(left, right);
    }
}

Pengujian yang tidak konsisten mengungkapkan kesalahan logika - diperbaiki

void merge_states(gsl::not_null<const state *> left, gsl::not_null<const state *> right)
{
    if (*left && *right)
        converge(left, right);
    else
    {
        // ...
        if (*left && *right)
            discard(left, right);
    }
}

Heuristik

Saat memastikan bahwa dereferensi pointer tidak null, aturan ini tidak mengharuskan setiap dereferensi memiliki pemeriksaan null sebelumnya. Sebaliknya, ini memerlukan pemeriksaan null sebelum dereferensi penunjuk terlebih dahulu . Fungsi berikut tidak memicu C26430:

void f(int* p)
{
    if (p)
        *p = 1;
    *p = 2;
}

Fungsi berikut menghasilkan C26430 karena ada jalur untuk ditetapkan *p tanpa pemeriksaan null:

void f(bool b, int* p)
{
    if (b && p)
        *p = 1;
    *p = 2;
}

Aturan C26822 dan C26823 berlaku untuk mendereferensikan pointer null (mungkin).

Aturan ini tidak melakukan pelacakan aliran data penuh. Ini dapat menghasilkan hasil yang salah dalam kasus di mana pemeriksaan tidak langsung digunakan, seperti ketika variabel perantara menyimpan nilai null dan kemudian digunakan dalam perbandingan.

Lihat juga

C26822
C26823