【发布时间】:2021-09-12 10:14:30
【问题描述】:
在某些情况下,潜在的无符号整数溢出可能会导致问题。这个例子说明了一个:
struct Image
{
uint32_t width;
uint32_t height;
uint32_t depth;
};
void* allocateMemory(size_t);
...
allocateMemory(f.width * f.height * f.depth);
GCC、clang 和 MSVC 的 x64 反汇编表明乘法将使用 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(包括 -Weverything)上启用了所有可能的警告,但没有报告上述代码中的问题。只有 MSVC 在编辑器 (C26451 Arithmetic overflow: Using operator * ...) 中报告了它,但我没有设法让它在构建时报告。
所以问题是如何在构建代码时发现这些类型的问题(没有运行时检查)。有没有可以捕捉到这一点的静态分析工具?或者也许是在使用 MSVC 构建时报告此 Intellisense C26451 警告的方法?
【问题讨论】:
-
我知道如何解决这个问题。问题是如何知道有问题需要解决。
-
该标准规定了无符号类型在溢出时会发生什么(即模运算又名“环绕”)。因此,如果可以配置您的编译器(或工具集的某些其他组件)以发出此类警告,那么在标准指定的行为是预期结果的情况下,您想做什么?
-
就标准而言,没有无符号整数溢出之类的东西。无符号类型实现模运算。在 C++ 中,您可以将整数包装在自定义类中,例如不允许乘法或以更高的宽度执行它,同时传递其他算术运算。
标签: c++ visual-c++ g++ clang++ gcc-warning