1

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

如果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

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);
}

它始于

Q_ASSERT_X(i >= 0 && i < p.size()

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

tool_menu->insertAction(action_list.at(action_list.count() - 2),
                                action);
4

4 回答 4

9

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

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()) {
    // ...
}

显然action_list.count()是一个常量值(至少在执行此代码时它不会改变),编译器能够弄清楚这一点。

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

你的if情况变成:

if (count - 2 >= 0 && count - 2 < count)

这相当于(假设,如编译器警告所说,没有发生溢出):

if (count >= 2 && -2 < 0)

后半部分-2 > 0显然是正确的,所以你可以放心地放弃它,这给我们留下了

if (count >= 2)

重新替换原始术语,这给了我们:

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) {
    // ...
}

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

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

如果您从编译器收到警告消息,您的目标不应该只是让消息消失;应该深入了解编译器警告您的内容,以及您的代码导致该问题的原因。

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

于 2013-08-29T23:06:20.447 回答
5

从这个GCC 资源

-Wstrict-溢出

-Wstrict-溢出=n

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

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


-Wstrict-溢出=1

对可疑且容易避免的情况发出警告。例如,使用 -fstrict-overflow,编译器将 x + 1 > x 简化为 1。 -Wstrict-overflow 的这一级别由 -Wall 启用;更高级别不是,必须明确要求。

-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。这仅在最高警告级别报告,因为这种简化适用于许多比较,因此此警告级别会产生大量误报。

于 2013-08-29T22:00:11.463 回答
1

解决方案是将我的整数更改为无符号整数:

const QList<QAction *> &action_list = tool_menu->actions();
static const unsigned int num_actions_to_skip = 2;
const unsigned int pos = action_list.count() - num_actions_to_skip;
assert(pos >= 0);
tool_menu->insertAction(action_list.at(pos),
                        action);
于 2013-08-30T04:01:33.273 回答
0

我刚刚解决了一个类似的问题,比较适用于 x86 但不适用于 arm(优化级别 O2):我将 (x<right) 替换为 (x-right<0) 并且代码现在很好。这听起来合乎逻辑(事后看来):新代码对人类来说更难阅读,但表达了编译器即使对溢出情况也做了什么。

static inline bool shape_int_rectangle_contains ( 
    const shape_int_rectangle_t *this_, int32_t x, int32_t y )
{
    bool result;
    const int32_t right = (*this_).left + (*this_).width;
    const int32_t bottom = (*this_).top + (*this_).height;
    /*
     * warning: assuming signed overflow does not occur when assuming that (X + c) >= X is always true [-Wstrict-overflow]
     *
     * result = ( x >= (*this_).left )&&( y >= (*this_).top )&&( x < right )&&( y < bottom );
     *
     * fix:
     */
    result = ( x-(*this_).left >= 0 )&&( y-(*this_).top >= 0 )&&( x-right < 0 )&&( y-bottom < 0 );
    return result;
}
于 2021-05-31T17:35:13.923 回答