Рассмотрим следующий проблемный код:

#include <iostream>

void foo(int64_t y) {
    std::cout << y << "\n";
}

int main() {
    uint64_t x = 14400000000000000000ull;
    foo(x);
}

Обычно печатает -4046744073709551616.

Как можно заставить компилятор помочь с этим типом проблемы преобразования / переполнения? Я пробовал следующее:

g++ -g overflow.cpp -fsanitize=undefined -Wall -Wextra -pedantic -Wconversion -Wconversion
clang++ -g overflow.cpp -fsanitize=undefined,integer,implicit-conversion -Wall -Wextra -pedantic

Ни один из них не дает предупреждений во время компиляции или выполнения.

(версия clang 7.0.0, версия gcc 8.2.1)

3
Zulan 22 Окт 2018 в 18:01

2 ответа

Лучший ответ

Проблема здесь в том, что -Wconversion будет предупреждать только в том случае, если значение, при приведении к исходному типу, может быть другого типа. Например, если foo должен был взять int вместо этого, то -Wconversion выдаст предупреждение, потому что возможно, что вы не сможете преобразовать значение в int обратно в исходное значение uint64_t. Если у нас есть

uint64_t u = some_value;
int64_t s = static_cast<int64_t>(u);
uint64_t check = static_cast<uint64_t>(s)

Тогда check == u всегда будет истинным (при условии, что int64_t также является дополнением к двум), поэтому -Wconversion не выдаст предупреждение, потому что мы вернем исходное значение.

В этом случае вам понадобится

-Wsign-conversion

Что предупредит вас о несоответствии знаков.

2
NathanOliver 22 Окт 2018 в 15:31

У GCC и Clang есть опция предупреждения -Wsign-conversion для выдачи предупреждения в таких случаях.

предупреждение: неявное преобразование изменяет подпись: 'uint64_t' (он же 'unsigned long') на 'int64_t' (он же 'long') [-Wsign-conversion]

Обратите внимание на документацию GCC о -Wconversion

... Предупреждения о преобразовании между знаковыми и беззнаковыми целыми числами по умолчанию отключены в C ++, если -Wsign-conversion не включен явно.

Также обратите внимание, что программа правильно сформирована (поэтому должна успешно компилироваться) и не имеет неопределенного поведения (и, следовательно, нет причин запускать дезинфицирующее средство). Преобразование непредставимого числа в подписанное приводит к значению, определяемому реализацией.

1
eerorika 22 Окт 2018 в 15:37
52932370