Bagikan melalui


Compiler Warning (level 4) C4754

Aturan konversi untuk operasi aritmatika dalam perbandingan berarti bahwa satu cabang tidak dapat dijalankan.

Peringatan C4754 dikeluarkan karena hasil perbandingan selalu sama. Ini menunjukkan bahwa salah satu cabang kondisi tidak pernah dijalankan, kemungkinan besar karena ekspresi bilangan bulat terkait salah. Cacat kode ini sering terjadi dalam pemeriksaan luapan bilangan bulat yang salah pada arsitektur 64-bit.

Aturan konversi bilangan bulat bersifat kompleks dan ada banyak jepitan yang halang. Sebagai alternatif untuk memperbaiki setiap peringatan C4754, Anda dapat memperbarui kode untuk menggunakan pustaka Brankas Int.

Contoh

Sampel ini menghasilkan C4754:

// C4754a.cpp
// Compile with: /W4 /c
#include "errno.h"

int sum_overflow(unsigned long a, unsigned long b)
{
   unsigned long long x = a + b; // C4754

   if (x > 0xFFFFFFFF)
   {
      // never executes!
      return EOVERFLOW;
   }
   return 0;
}

Penambahan a + b dapat menyebabkan luapan aritmatika sebelum hasilnya ditingkatkan ke nilai 64-bit dan ditetapkan ke variabel x64-bit . Ini berarti bahwa pemeriksaan x berlebihan dan tidak akan pernah menangkap luapan. Dalam hal ini, pengkompilasi mengeluarkan peringatan ini:

Warning C4754: Conversion rules for arithmetic operations in the comparison at C4754a.cpp (7) mean that one branch cannot be executed. Cast '(a + ...)' to 'ULONG64' (or similar type of 8 bytes).

Untuk menghilangkan peringatan, Anda dapat mengubah pernyataan penetapan untuk mentransmisikan operand menjadi nilai 8-byte:

// Casting one operand is sufficient to force all the operands in
// the addition be upcast according to C/C++ conversion rules, but
// casting both is clearer.
unsigned long long x =
   (unsigned long long)a + (unsigned long long)b;

Sampel berikutnya juga menghasilkan C4754.

// C4754b.cpp
// Compile with: /W4 /c
#include "errno.h"

int wrap_overflow(unsigned long a)
{
   if (a + sizeof(unsigned long) < a) // C4754
   {
      // never executes!
      return EOVERFLOW;
   }
   return 0;
}

Operator sizeof() mengembalikan size_t, yang ukurannya tergantung arsitektur. Contoh kode bekerja pada arsitektur 32-bit di mana adalah size_t jenis 32-bit. Namun, pada arsitektur 64-bit, size_t adalah jenis 64-bit. Aturan konversi untuk bilangan bulat berarti yang a ditingkatkan ke nilai 64-bit dalam ekspresi a + b < a seolah-olah ditulis (size_t)a + (size_t)b < (size_t)a. Ketika a dan b adalah bilangan bulat 32-bit, operasi penambahan 64-bit tidak pernah dapat meluap, dan batasan tidak pernah ada. Akibatnya, kode tidak pernah mendeteksi kondisi luapan bilangan bulat pada arsitektur 64-bit. Contoh ini menyebabkan pengkompilasi memancarkan peringatan ini:

Warning C4754: Conversion rules for arithmetic operations in the comparison at C4754b.cpp (7) mean that one branch cannot be executed. Cast '4' to 'ULONG' (or similar type of 4 bytes).

Perhatikan bahwa pesan peringatan secara eksplisit mencantumkan nilai konstanta 4 alih-alih string sumber asliā€”pada saat analisis peringatan menemukan kode yang menyinggung, sizeof(unsigned long) telah dikonversi ke konstanta. Oleh karena itu, Anda mungkin harus melacak ekspresi mana dalam kode sumber yang terkait dengan nilai konstanta dalam pesan peringatan. Sumber kode yang paling umum diselesaikan ke konstanta dalam pesan peringatan C4754 adalah ekspresi seperti sizeof(TYPE) dan strlen(szConstantString).

Dalam hal ini, kode tetap akan menyerupai ini:

// Casting the result of sizeof() to unsigned long ensures
// that all the addition operands are 32-bit, so any overflow
// is detected by the check.
if (a + (unsigned long)sizeof(unsigned long) < a)

Catatan Nomor baris yang dimaksud dalam peringatan kompilator adalah baris terakhir dari pernyataan. Dalam pesan peringatan tentang pernyataan kondisi yang kompleks yang tersebar di beberapa baris, baris yang memiliki cacat kode mungkin beberapa baris sebelum baris yang dilaporkan. Contohnya:

unsigned long a;

if (a + sizeof(unsigned long) < a || // incorrect check
    condition1() ||
    a == 0) {    // C4754 warning reported on this line
         // never executes!
         return INVALID_PARAMETER;
}