#c #visual-c #g #clang #gcc-warning
Вопрос:
Есть некоторые случаи, когда потенциальные переполнения целочисленных без знака могут вызвать проблемы. Этот пример иллюстрирует один:
struct Image
{
uint32_t width;
uint32_t height;
uint32_t depth;
};
void* allocateMemory(size_t);
...
allocateMemory(f.width * f.height * f.depth);
64-разрядная разборка GCC, clang и MSVC показывает, что умножение будет выполняться с использованием 32-разрядной арифметики. Это может привести к переполнению при наличии длинного списка умножений.
mov eax, dword ptr [rdi 4]
imul eax, dword ptr [rdi]
imul eax, dword ptr [rdi 8]
mov rdi, rax
Эта ссылка на godbolt содержит приведенный выше пример и разборку 3 популярных компиляторов: https://godbolt.org/z/1P1bT3jj6
Я включил все возможные предупреждения о GCC и clang (включая-Все), но ни одно из них не сообщает о проблемах в приведенном выше коде. Только MSVC сообщил об этом в редакторе ( C26451 Arithmetic overflow: Using operator * ...
), но мне не удалось заставить его сообщить об этом во время сборки.
Таким образом, вопрос в том, как уловить эти типы проблем при создании кода (без проверок во время выполнения). Есть ли инструмент статического анализа, который может это уловить? Или, может быть, способ сообщить об этом C26451
предупреждении Intellisense при сборке с помощью MSVC?
Комментарии:
1. Я знаю, как решить эту проблему. Вопрос в том, как узнать, что есть проблема, которую нужно исправить.
2. Стандарт определяет, что происходит с типами без знака при переполнении (т. Е. по модулю арифметики, он же «обертывание»). Итак, если возможно настроить ваш компилятор (или какой-либо другой компонент вашего набора инструментов) для выдачи таких предупреждений, что вы хотите делать в случаях, когда поведение, указанное стандартом, является ПРЕДПОЛАГАЕМЫМ результатом?
3. Что касается стандарта, то такого понятия, как переполнение целых чисел без знака, не существует. Типы без знака реализуют модульную арифметику. В C вы можете обернуть целые числа в пользовательский класс, который, например, запрещает умножение или выполняет его с большей шириной, выполняя при этом другие арифметические операции.
Ответ №1:
Для MSVC вы можете включить предупреждения, такие как C26451, во время сборки, включив «Анализ кода» в свойствах проекта (или файла) 1:
Кроме того, вы можете запустить этот анализ кода в открытом/активном файле в любое время, используя команду «Запустить анализ кода в файле» из меню «Сборка» (или Ctrl Shift Alt f7).
Вы можете включить эту опцию в командной строке с помощью /analyze
переключателя; однако вам нужно будет указать «плагины» для анализа кода (которые поставляются с Visual Studio) для использования (типичный вариант будет примерно /analyze:plugin EspxEngine.dll
таким ). Обзор этого приведен на этой веб-странице Microsoft в разделе «Параметры плагина анализа». Следующий пункт представляется особенно актуальным:
При построении в командной строке вы можете использовать переменную среды Esp.Extensions для указания расширений EspXEngine. Например:
set Esp.Extensions=ConcurrencyCheck.dll;CppCoreCheck.dll;
1 Но обратите внимание, что эта опция значительно увеличит время сборки, что может стать проблематичным для крупных проектов.
Комментарии:
1. Есть идеи, как включить это из командной строки (я использую CMake)? Я верю, что это
/analyze
так, но тестирование на gotbolt ничего не меняет.2. @Пан Хмм. Не совсем уверен. Отключение опции, показанной выше, и добавление
/analyze
переключателя в параметры командной строки компилятора (в реальном VS, а не в проводнике компилятора) также не показывает предупреждение C26451. Вероятно, потребуется указать файл набора правил, который может быть недоступен онлайн-составителям.3. @Pan. Кристопулосаритос … Да! Использование параметра
/analyze:plugin EspxEngine.dll
командной строки работает.