假设在if语句中不会发生签名溢出

cla*_*ark 1 c++ qt g++

为什么会出现此警告?如果我检查边界,这不是一个真正的假设.以及如何解决?

如果num_actions_to_skip设置为1而不是2,则错误消失.

谢谢

error: assuming signed overflow does not occur when assuming that (X - c) <= X is always true [-Werror=strict-overflow]
cc1plus: all warnings being treated as errors
Run Code Online (Sandbox Code Playgroud)

if (loc >= 0 && loc < action_list.count()) {

const QList<QAction *> &action_list = tool_menu->actions();
static const int num_actions_to_skip = 2;
const int loc = action_list.count() - num_actions_to_skip;
if (loc >= 0 && loc < action_list.count()) {
    tool_menu->insertAction(action_list.at(loc),
                            action);
}
Run Code Online (Sandbox Code Playgroud)

它始于

Q_ASSERT_X(i >= 0 && i < p.size()
Run Code Online (Sandbox Code Playgroud)

在qlist.h:454,执行相同的检查,并抛出此错误,只是

tool_menu->insertAction(action_list.at(action_list.count() - 2),
                                action);
Run Code Online (Sandbox Code Playgroud)

Kei*_*son 8

你只需要重新思考你的逻辑.

static const int num_actions_to_skip = 2;
const int loc = action_list.count() - num_actions_to_skip;
if (loc >= 0 && loc < action_list.count()) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

显然action_list.count()是一个常量值(至少它不会随着执行此代码而改变),编译器能够解决这个问题.

让我们简化一下,替换num_actions_to_skip2,减少action_list.count()count.然后我们可以重新表达loccount - 2.

你的if病情变成:

if (count - 2 >= 0 && count - 2 < count)
Run Code Online (Sandbox Code Playgroud)

这是等效的(假设,正如编译器警告所说,没有发生溢出):

if (count >= 2 && -2 < 0)
Run Code Online (Sandbox Code Playgroud)

下半部分,-2 > 0显然是正确的,所以你可以安全地放弃它,这让我们失望了

if (count >= 2)
Run Code Online (Sandbox Code Playgroud)

重新替换原始条款,这给了我们:

static const int num_actions_to_skip = 2;
// const int loc = action_list.count() - num_actions_to_skip;
if (action_list.count() >= num_actions_to_skip) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

编译器警告您,如果存在整数溢出,它正在执行可能无效的优化(允许假设没有溢出,因为如果行为未定义).它很友好地警告你 - 这对你来说很幸运,因为它指出你的代码正在做一些它不需要的事情.

我不知道你是否需要保留声明loc; 这取决于你以后是否使用它.但是如果你按照我建议的方式简化代码,它应该以相同的方式工作,并且更容易阅读和理解.

如果您收到编译器发出的警告消息,那么您的目标不应仅仅是让消息消失; 它应该是向下钻取并找出编译器警告你的内容,以及你的代码导致该问题的原因.

您比我更了解此代码的上下文.如果您查看修订版本,您可能会发现它更清楚地表达了意图.


Buh*_*ndi 5

从这个GCC资源:

-Wstrict溢出

-Wstrict溢出=正

此选项仅在-fstrict-overflow处于活动状态时处于活动状态.它会警告编译器根据没有发生签名溢出的假设进行优化的情况.请注意,它不会警告代码可能溢出的所有情况:它只会警告编译器实现某些优化的情况.因此,此警告取决于优化级别.

如果所涉及的变量的值实际上发生溢出,那么假定未发生签名溢出的优化是完全安全的.因此,此警告很容易产生误报:对代码实际上不是问题的警告.为了帮助关注重要问题,定义了几个警告级别.在估计循环所需的迭代次数时,不会发出使用未定义的有符号溢出的警告,特别是在确定是否将执行循环时.


-Wstrict溢出= 1

警告有疑问且容易避免的案件.例如,使用-fstrict-overflow,编译器将x + 1> x简化为1. -Wall启用此级别的-Wstrict-overflow; 更高级别不是,必须明确要求.

-Wstrict溢出= 2

还警告其他比较被简化为常数的情况.例如:abs(x)> = 0.这只能在-fstrict-overflow有效时简化,因为abs(INT_MIN)溢出到INT_MIN,小于零.-Wstrict-overflow(没有级别)与-Wstrict-overflow = 2相同.

-Wstrict溢出= 3

还警告其他简化比较的情况.例如:x + 1> 1被简化为x> 0.

-Wstrict溢出= 4

还警告上述案例未涵盖的其他简化.例如:(x*10)/ 5简化为x*2.

-Wstrict溢出= 5

还要警告编译器减少比较中涉及的常量的大小的情况.例如:x + 2> y被简化为x + 1> = y.这仅在最高警告级别报告,因为此简化适用于许多比较,因此此警告级别会产生大量误报.

  • @foxrider67:不,编译器不会将`int`“优化”为`unsigned int`。您正在使用的值是整数;将它们更改为“double”不是答案。你需要重新安排你的逻辑(我还没有研究过这个,不知道怎么做)。 (2认同)