用于检查整数溢出的编译器标志

4
在下面的程序中,我们如何使编译器在算术表达式存在问题时发出警告/错误?
如果算术表达式的结果超过其类型的最大值,我希望编译器发出警告/错误。
我使用的编译器是gcc(GCC)4.8.5 20150623(Red Hat 4.8.5-4),使用的编译命令是gcc int_promo_flags.c -Wall -Wextra 我期望从代码行long long int y = x + INT_MAX;中得到一个警告/错误,但没有报告任何错误/警告。
通过将x强制转换为(long long) x,我们可以使表达式产生正确的值。 但是否有编译器标志可以在算术表达式要溢出其参数类型时发出警告?
#include <stdio.h>
#include <limits.h>

int main()
{
    int x = 1;
    long long int y = (long long) x + INT_MAX;
    printf("%lld\n", y);
    return 0;
}

long long 可能比 INT_MAX(4 字节)+1 大得多(8 字节)https://godbolt.org/z/GezYEcejj - yano
“long long”有点误导人,因为这些值的算术运算无论如何都会溢出,但对于“int x = -1”则不会。程序员需要注意整数范围。如果这是一个函数,并且“int x”作为参数传递(其运行时值未知),您是否希望收到警告? - Weather Vane
int a, b; /* ... a>0, b>0 ... */ if (a > INT_MAX - b) fprintf(stderr, "a + b overflows\n"); - pmg
1
@WeatherVane,我同意你的看法,如果代码很大的话,个人很难追踪所有的代码以解决这些问题。我只是很好奇是否有任何标志可用,以便使其更容易 :) - IrAM
这只是一个练习问题。如果算术结果应该是更大的类型,那么你应该知道它有可能会溢出。这类似于“int x=3, y=2; float z=x/y”这种错误。 - Weather Vane
2个回答

5

如果你在gcc中使用-ftrapv标志,你可以强制你的程序在整数溢出时中止。

例如,删除转换并使用-ftrapv编译,你的程序会中止:

int x = 1;
long long int y = x + INT_MAX;
printf("%lld\n", y);
return 0;

> gcc main.c -ftrapv -o overflow
> ./overflow
fish: Job 1, './overflow' terminated by signal SIGABRT (Abort)

我认为主流编译器不支持带符号整数溢出的编译时警告,但您可以在运行时手动检查它们。


是的,我看到了这个帖子,那里也提到了-ftrapv。我只想知道在编译时是否可以检测到。 - IrAM
很遗憾,我认为编译器不提供这种功能。 - Daniel Kleinstein

1

使用离线分析查找溢出是一个复杂的算法问题。假设内存资源无限,可能是图灵完备的。

然而,可以使用内置的清洗器在运行时查找这样的溢出。

只需使用-fsanitize=undefined选项进行编译即可。我已经删除了强制转换,因为INT_MAX不足以使long long溢出。

#include <stdio.h>
#include <limits.h>

int main()
{
    int x = 1;
    long long int y = x + INT_MAX;
    printf("%lld\n", y);
    return 0;
}

运行生成了以下报告:

prog.c:7:25: runtime error: signed integer overflow: 1 + 2147483647 cannot be represented in type 'int'
-2147483648

有各种各样的消毒剂,通常会产生关于违规的非常好的报告。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接