过度使用 gcc 消毒剂
Overreaching gcc sanitizer
我这里有这个小片段:
static int32_t s_pow(int32_t base, int32_t exponent)
{
int32_t result = 1;
while (exponent != 0) {
if ((exponent % 2) == 1) {
result *= base;
}
exponent /= 2;
base *= base; /* <- this line */
}
return result;
}
小巧玲珑,正是我需要的。
但是 GCC 7.5.0(以及其他支持检查的较新版本)抱怨:
gcc -I./ -Wall -Wsign-compare -Wextra -Wshadow -fsanitize=undefined\
-fno-sanitize-recover=all -fno-sanitize=float-divide-by-zero\
-Wdeclaration-after-statement -Wbad-function-cast -Wcast-align -Wstrict-prototypes\
-Wpointer-arith -Wsystem-headers -O3 -funroll-loops -fomit-frame-pointer -flto -m64\
test.o -o test
test.c:25:12: runtime error: signed integer overflow: 65536 * 65536 cannot be represented in type 'int'
是的,GCC,这是正确的,即使在 64 位环境中,65536 * 65536 对于 31 位数据类型来说有点多,承认。但是输入来自一个小的 table 并且经过精心选择,使得结果 result
不能超过 2^20
,因此中间结果的 none 可以。我不能只改变我的代码的消毒本身。是的,我检查了所有可能的结果。
有什么想法吗?还是我的代码?
如我所见,runtime error: signed integer overflow
发生在运行时。这意味着您发送了一个指向 UB 的输入。你说那个result cannot exceed 2^20
。正如我猜你的意思是你有这样的情况,你在已经得到结果后进行 base *= base
操作,并且不再关心 base
。
如果我没理解错的话,我猜你可以把代码改成这样?
例如,它会给你一个 s_pow(60000, 1)
调用的修复,并且不会影响性能,因为这里的编译器优化很容易。
static int32_t s_pow(int32_t base, int32_t exponent) {
int32_t result = 1;
while (exponent != 0) {
if ((exponent % 2) == 1) {
result *= base;
}
exponent /= 2;
if (exponent == 0) {
break;
}
base *= base; /* <- this line */
}
return result;
}
基本上了解你想要什么很重要,如果你想删除恼人的警告,这里有一个方法。如果仍然出现警告,可能是您发送的数字太大了。
我这里有这个小片段:
static int32_t s_pow(int32_t base, int32_t exponent)
{
int32_t result = 1;
while (exponent != 0) {
if ((exponent % 2) == 1) {
result *= base;
}
exponent /= 2;
base *= base; /* <- this line */
}
return result;
}
小巧玲珑,正是我需要的。 但是 GCC 7.5.0(以及其他支持检查的较新版本)抱怨:
gcc -I./ -Wall -Wsign-compare -Wextra -Wshadow -fsanitize=undefined\
-fno-sanitize-recover=all -fno-sanitize=float-divide-by-zero\
-Wdeclaration-after-statement -Wbad-function-cast -Wcast-align -Wstrict-prototypes\
-Wpointer-arith -Wsystem-headers -O3 -funroll-loops -fomit-frame-pointer -flto -m64\
test.o -o test
test.c:25:12: runtime error: signed integer overflow: 65536 * 65536 cannot be represented in type 'int'
是的,GCC,这是正确的,即使在 64 位环境中,65536 * 65536 对于 31 位数据类型来说有点多,承认。但是输入来自一个小的 table 并且经过精心选择,使得结果 result
不能超过 2^20
,因此中间结果的 none 可以。我不能只改变我的代码的消毒本身。是的,我检查了所有可能的结果。
有什么想法吗?还是我的代码?
如我所见,runtime error: signed integer overflow
发生在运行时。这意味着您发送了一个指向 UB 的输入。你说那个result cannot exceed 2^20
。正如我猜你的意思是你有这样的情况,你在已经得到结果后进行 base *= base
操作,并且不再关心 base
。
如果我没理解错的话,我猜你可以把代码改成这样?
例如,它会给你一个 s_pow(60000, 1)
调用的修复,并且不会影响性能,因为这里的编译器优化很容易。
static int32_t s_pow(int32_t base, int32_t exponent) {
int32_t result = 1;
while (exponent != 0) {
if ((exponent % 2) == 1) {
result *= base;
}
exponent /= 2;
if (exponent == 0) {
break;
}
base *= base; /* <- this line */
}
return result;
}
基本上了解你想要什么很重要,如果你想删除恼人的警告,这里有一个方法。如果仍然出现警告,可能是您发送的数字太大了。