首页 > 解决方案 > 过度使用 gcc 消毒剂

问题描述

我在这里有这个小片段:

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,这是正确的,承认 65536 * 65536 对于 31 位数据类型来说有点多,即使在 64 位环境中也是如此。但是输入来自一个小表,并且经过精心选择,结果result不能超过2^20,因此没有一个中间结果可以。我不能只更改我的代码本身的消毒。是的,我检查了所有可能的结果。

有任何想法吗?还是我的代码?

标签: cinteger-overflowgcc-warning

解决方案


正如我所见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;
}

基本上了解你想要什么很重要,如果你想消除烦人的警告,这是一种方法。如果仍然出现警告,则可能是您发送的数字太大。


推荐阅读