Share via


Upozornění kompilátoru (úroveň 4) C4754

Pravidla převodu pro aritmetické operace v porovnání znamenají, že jednu větev nelze spustit.

Upozornění C4754 je vydáno, protože výsledek porovnání je vždy stejný. To znamená, že jedna z větví podmínky se nikdy nespustí, pravděpodobně proto, že přidružený celočíselné výraz je nesprávný. Tato chyba kódu se často vyskytuje v nesprávných kontrolách přetečení celého čísla v 64bitových architekturách.

Celočíselná pravidla převodu jsou složitá a existuje mnoho drobných nástrah. Jako alternativu k opravě každého upozornění C4754 můžete kód aktualizovat tak, aby používal knihovnu Sejf Int.

Příklady

Tato ukázka vygeneruje 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;
}

Přidání a + b může způsobit aritmetický přetečení před tím, než se výsledek přepíná na 64bitovou hodnotu a přiřadí se k 64bitové proměnné x. To znamená, že kontrola x je redundantní a nikdy nezachytí přetečení. V tomto případě kompilátor vygeneruje toto upozornění:

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).

Pokud chcete upozornění odstranit, můžete změnit příkaz přiřazení tak, aby přetypoval operandy na hodnoty 8 bajtů:

// 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;

Další ukázka také vygeneruje 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;
}

Operátor sizeof() vrátí size_thodnotu , jejíž velikost je závislá na architektuře. Ukázkový kód funguje na 32bitových architekturách, kde size_t je 32bitový typ. U 64bitových size_t architektur je však 64bitový typ. Pravidla převodu pro celá čísla znamenají, že a je v výrazu a + b < a upcast na 64bitovou hodnotu, jako by byla zapsána (size_t)a + (size_t)b < (size_t)a. Pokud a a b jsou 32bitová celá čísla, 64bitová operace sčítání nikdy nemůže přetékat a omezení nikdy neudrží. V důsledku toho kód nikdy nezjistí celočíselnou podmínku přetečení v 64bitových architekturách. Tento příklad způsobí, že kompilátor vygeneruje toto upozornění:

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).

Všimněte si, že zpráva upozornění explicitně uvádí hodnotu konstanty 4 místo původního zdrojového řetězce – v době, kdy analýza upozornění narazí na off-endový kód, sizeof(unsigned long) již byla převedena na konstantu. Proto možná budete muset zjistit, který výraz ve zdrojovém kódu je přidružen k konstantní hodnotě ve zprávě upozornění. Nejběžnějšími zdroji kódu vyřešené na konstanty v upozorněních C4754 jsou výrazy jako sizeof(TYPE) a strlen(szConstantString).

V tomto případě by pevný kód vypadal takto:

// 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)

Poznámka: Číslo řádku uvedené v upozorněních kompilátoru je poslední řádek příkazu. V upozornění na složitý podmíněný příkaz, který je rozložen na více řádků, může být řádek s kódem vad několik řádků před oznamované čárou. Příklad:

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;
}