Derleyici Uyarısı (düzey 4) C4754
Karşılaştırmada aritmetik işlemler için dönüştürme kuralları, bir dalın yürütülemeyeceği anlamına gelir.
Karşılaştırmanın sonucu her zaman aynı olduğundan C4754 uyarısı verilir. Bu, büyük olasılıkla ilişkili tamsayı ifadesi yanlış olduğundan koşulun dallarından birinin hiçbir zaman yürütülmeyeceğini gösterir. Bu kod hatası genellikle 64 bit mimarilerde yanlış tamsayı taşması denetimlerinde oluşur.
Tamsayı dönüştürme kuralları karmaşıktır ve birçok küçük tuzak vardır. Her C4754 uyarısını düzeltmeye alternatif olarak, Kodu SafeInt Kitaplığı'nı kullanacak şekilde güncelleştirebilirsiniz.
Örnekler
Bu örnek C4754 oluşturur:
// 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;
}
Toplama a + b
işlemi, sonuç 64 bit değerine yukarı yayınlanıp 64 bit değişkenine x
atanmadan önce aritmetik taşmaya neden olabilir. Bu, denetimin x
yedekli olduğu ve hiçbir zaman taşma yakalamayacağı anlamına gelir. Bu durumda, derleyici şu uyarıyı yayar:
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).
Uyarıyı ortadan kaldırmak için atama deyimini, işlenenleri 8 baytlık değerlere dönüştürecek şekilde değiştirebilirsiniz:
// 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;
Sonraki örnek ayrıca C4754 oluşturur.
// 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;
}
işleci sizeof()
, boyutu mimariye bağımlı olan bir size_t
döndürür. Örnek kod, 32 bit türünde olan size_t
32 bit mimarilerde çalışır. Ancak, 64 bit mimarilerde size_t
64 bit türündedir. Tamsayılar için dönüştürme kuralları, ifadede a + b < a
yazılmış (size_t)a + (size_t)b < (size_t)a
gibi 64 bitlik bir değere yukarı yayın olduğu anlamına gelira
. a
ve b
32 bit tamsayı olduğunda, 64 bit toplama işlemi hiçbir zaman taşmaz ve kısıtlama hiçbir zaman geçerli olmaz. Sonuç olarak, kod 64 bit mimarilerde hiçbir zaman tamsayı taşması koşulu algılamaz. Bu örnek, derleyicinin bu uyarıyı yaymasına neden olur:
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).
Uyarı iletisinde özgün kaynak dize yerine 4 sabit değerinin açıkça listelendiğine dikkat edin. Uyarı çözümlemesi sorunlu kodla karşılaştığında, sizeof(unsigned long)
zaten sabite dönüştürülmüştür. Bu nedenle, kaynak koddaki hangi ifadenin uyarı iletisindeki sabit değerle ilişkili olduğunu izlemeniz gerekebilir. C4754 uyarı iletilerinde sabitlere çözümlenen en yaygın kod kaynakları ve strlen(szConstantString)
gibi sizeof(TYPE)
ifadelerdir.
Bu durumda, sabit kod şuna benzer olacaktır:
// 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)
Not Derleyici uyarılarında başvuruda bulunılan satır numarası, deyiminin son satırıdır. Birden çok satıra yayılan karmaşık bir koşullu deyimle ilgili bir uyarı iletisinde, kod hatasını içeren satır, bildirilen satırdan önce birkaç satır olabilir. Örnek:
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;
}