为什么c++对两个无符号数使用jle而不是jbe ?



在这种情况下,我得到这个错误:

错误:假设在简化条件

时没有发生符号溢出

我看了看汇编和if()使用:

d34:   48 83 fa 01             cmp    $0x1,%rdx
d38:   7e 54                   jle    d8e <main+0x3ae>

有趣的是,%rdx被定义为无符号数(std::size_t),$0x1也被定义为无符号数(原文为2UL)。那么为什么g++决定使用jle而不是jbe呢?

注意:以防万一,我尝试了if(colons > 1UL) ...,但没有帮助。同样的错误,同样的结果。


c++代码重现错误:

#include <algorithm>
#include <string>
#include <iostream>
int main(int argc, char * argv[])
{
std::string const in(argv[1]);
std::size_t const colons(std::count(in.begin(), in.end(), ':'));
if(colons >= 2UL)
{
std::cerr << "2 or more colons...n";
}
else
{
std::cerr << "no or just one colon.n";
}
return 0;
}

用于重现错误的命令行:

g++ -Werror=strict-overflow -std=c++17 -O3 -o a a.cpp

无论如何,不要使用-Werror=strict-overflow选项来编译。

完整的结果(这是一个杀手,因为std::count()对速度进行了过度优化):
00000000000009e0 <main>:
9e0:   41 55                   push   %r13
9e2:   41 54                   push   %r12
9e4:   55                      push   %rbp
9e5:   53                      push   %rbx
9e6:   48 83 ec 38             sub    $0x38,%rsp
9ea:   4c 8b 66 08             mov    0x8(%rsi),%r12
9ee:   48 89 e3                mov    %rsp,%rbx
9f1:   4c 8d 6b 10             lea    0x10(%rbx),%r13
9f5:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
9fc:   00 00 
9fe:   48 89 44 24 28          mov    %rax,0x28(%rsp)
a03:   31 c0                   xor    %eax,%eax
a05:   4d 85 e4                test   %r12,%r12
a08:   4c 89 2c 24             mov    %r13,(%rsp)
a0c:   0f 84 e8 03 00 00       je     dfa <main+0x41a>
a12:   4c 89 e7                mov    %r12,%rdi
a15:   e8 16 ff ff ff          callq  930 <strlen@plt>
a1a:   48 83 f8 0f             cmp    $0xf,%rax
a1e:   48 89 c5                mov    %rax,%rbp
a21:   0f 87 7c 03 00 00       ja     da3 <main+0x3c3>
a27:   48 83 f8 01             cmp    $0x1,%rax
a2b:   0f 84 4f 03 00 00       je     d80 <main+0x3a0>
a31:   48 85 c0                test   %rax,%rax
a34:   0f 85 cc 03 00 00       jne    e06 <main+0x426>
a3a:   48 8b 04 24             mov    (%rsp),%rax
a3e:   48 89 6c 24 08          mov    %rbp,0x8(%rsp)
a43:   c6 04 28 00             movb   $0x0,(%rax,%rbp,1)
a47:   48 8b 04 24             mov    (%rsp),%rax
a4b:   48 8b 54 24 08          mov    0x8(%rsp),%rdx
a50:   48 8d 34 10             lea    (%rax,%rdx,1),%rsi
a54:   48 39 f0                cmp    %rsi,%rax
a57:   0f 84 31 03 00 00       je     d8e <main+0x3ae>
a5d:   48 89 c1                mov    %rax,%rcx
a60:   49 89 f1                mov    %rsi,%r9
a63:   48 83 ea 01             sub    $0x1,%rdx
a67:   48 f7 d9                neg    %rcx
a6a:   49 29 c1                sub    %rax,%r9
a6d:   41 ba 12 00 00 00       mov    $0x12,%r10d
a73:   83 e1 0f                and    $0xf,%ecx
a76:   48 8d 78 01             lea    0x1(%rax),%rdi
a7a:   4c 8d 41 0f             lea    0xf(%rcx),%r8
a7e:   49 83 f8 12             cmp    $0x12,%r8
a82:   4d 0f 42 c2             cmovb  %r10,%r8
a86:   4c 39 c2                cmp    %r8,%rdx
a89:   0f 82 4b 03 00 00       jb     dda <main+0x3fa>
a8f:   48 85 c9                test   %rcx,%rcx
a92:   0f 84 52 03 00 00       je     dea <main+0x40a>
a98:   45 31 d2                xor    %r10d,%r10d
a9b:   80 38 3a                cmpb   $0x3a,(%rax)
a9e:   41 0f 94 c2             sete   %r10b
aa2:   48 83 f9 01             cmp    $0x1,%rcx
aa6:   0f 84 34 01 00 00       je     be0 <main+0x200>
aac:   80 78 01 3a             cmpb   $0x3a,0x1(%rax)
ab0:   75 04                   jne    ab6 <main+0xd6>
ab2:   49 83 c2 01             add    $0x1,%r10
ab6:   48 83 f9 02             cmp    $0x2,%rcx
aba:   48 8d 78 02             lea    0x2(%rax),%rdi
abe:   0f 84 1c 01 00 00       je     be0 <main+0x200>
ac4:   80 78 02 3a             cmpb   $0x3a,0x2(%rax)
ac8:   75 04                   jne    ace <main+0xee>
aca:   49 83 c2 01             add    $0x1,%r10
ace:   48 83 f9 03             cmp    $0x3,%rcx
ad2:   48 8d 78 03             lea    0x3(%rax),%rdi
ad6:   0f 84 04 01 00 00       je     be0 <main+0x200>
adc:   80 78 03 3a             cmpb   $0x3a,0x3(%rax)
ae0:   75 04                   jne    ae6 <main+0x106>
ae2:   49 83 c2 01             add    $0x1,%r10
ae6:   48 83 f9 04             cmp    $0x4,%rcx
aea:   48 8d 78 04             lea    0x4(%rax),%rdi
aee:   0f 84 ec 00 00 00       je     be0 <main+0x200>
af4:   80 78 04 3a             cmpb   $0x3a,0x4(%rax)
af8:   75 04                   jne    afe <main+0x11e>
afa:   49 83 c2 01             add    $0x1,%r10
afe:   48 83 f9 05             cmp    $0x5,%rcx
b02:   48 8d 78 05             lea    0x5(%rax),%rdi
b06:   0f 84 d4 00 00 00       je     be0 <main+0x200>
b0c:   80 78 05 3a             cmpb   $0x3a,0x5(%rax)
b10:   75 04                   jne    b16 <main+0x136>
b12:   49 83 c2 01             add    $0x1,%r10
b16:   48 83 f9 06             cmp    $0x6,%rcx
b1a:   48 8d 78 06             lea    0x6(%rax),%rdi
b1e:   0f 84 bc 00 00 00       je     be0 <main+0x200>
b24:   80 78 06 3a             cmpb   $0x3a,0x6(%rax)
b28:   0f 84 9a 02 00 00       je     dc8 <main+0x3e8>
b2e:   48 83 f9 07             cmp    $0x7,%rcx
b32:   48 8d 78 07             lea    0x7(%rax),%rdi
b36:   0f 84 a4 00 00 00       je     be0 <main+0x200>
b3c:   80 78 07 3a             cmpb   $0x3a,0x7(%rax)
b40:   0f 84 8b 02 00 00       je     dd1 <main+0x3f1>
b46:   48 83 f9 08             cmp    $0x8,%rcx
b4a:   48 8d 78 08             lea    0x8(%rax),%rdi
b4e:   0f 84 8c 00 00 00       je     be0 <main+0x200>
b54:   80 78 08 3a             cmpb   $0x3a,0x8(%rax)
b58:   75 04                   jne    b5e <main+0x17e>
b5a:   49 83 c2 01             add    $0x1,%r10
b5e:   48 83 f9 09             cmp    $0x9,%rcx
b62:   48 8d 78 09             lea    0x9(%rax),%rdi
b66:   74 78                   je     be0 <main+0x200>
b68:   80 78 09 3a             cmpb   $0x3a,0x9(%rax)
b6c:   75 04                   jne    b72 <main+0x192>
b6e:   49 83 c2 01             add    $0x1,%r10
b72:   48 83 f9 0a             cmp    $0xa,%rcx
b76:   48 8d 78 0a             lea    0xa(%rax),%rdi
b7a:   74 64                   je     be0 <main+0x200>
b7c:   80 78 0a 3a             cmpb   $0x3a,0xa(%rax)
b80:   75 04                   jne    b86 <main+0x1a6>
b82:   49 83 c2 01             add    $0x1,%r10
b86:   48 83 f9 0b             cmp    $0xb,%rcx
b8a:   48 8d 78 0b             lea    0xb(%rax),%rdi
b8e:   74 50                   je     be0 <main+0x200>
b90:   80 78 0b 3a             cmpb   $0x3a,0xb(%rax)
b94:   75 04                   jne    b9a <main+0x1ba>
b96:   49 83 c2 01             add    $0x1,%r10
b9a:   48 83 f9 0c             cmp    $0xc,%rcx
b9e:   48 8d 78 0c             lea    0xc(%rax),%rdi
ba2:   74 3c                   je     be0 <main+0x200>
ba4:   80 78 0c 3a             cmpb   $0x3a,0xc(%rax)
ba8:   75 04                   jne    bae <main+0x1ce>
baa:   49 83 c2 01             add    $0x1,%r10
bae:   48 83 f9 0d             cmp    $0xd,%rcx
bb2:   48 8d 78 0d             lea    0xd(%rax),%rdi
bb6:   74 28                   je     be0 <main+0x200>
bb8:   80 78 0d 3a             cmpb   $0x3a,0xd(%rax)
bbc:   75 04                   jne    bc2 <main+0x1e2>
bbe:   49 83 c2 01             add    $0x1,%r10
bc2:   48 83 f9 0f             cmp    $0xf,%rcx
bc6:   48 8d 78 0e             lea    0xe(%rax),%rdi
bca:   75 14                   jne    be0 <main+0x200>
bcc:   80 78 0e 3a             cmpb   $0x3a,0xe(%rax)
bd0:   0f 84 0b 02 00 00       je     de1 <main+0x401>
bd6:   48 8d 78 0f             lea    0xf(%rax),%rdi
bda:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
be0:   49 29 c9                sub    %rcx,%r9
be3:   66 45 0f ef c0          pxor   %xmm8,%xmm8
be8:   66 0f ef e4             pxor   %xmm4,%xmm4
bec:   4d 89 c8                mov    %r9,%r8
bef:   66 0f ef db             pxor   %xmm3,%xmm3
bf3:   48 01 c8                add    %rcx,%rax
bf6:   66 0f ef d2             pxor   %xmm2,%xmm2
bfa:   49 c1 e8 04             shr    $0x4,%r8
bfe:   66 0f 6f 35 5a 04 00    movdqa 0x45a(%rip),%xmm6        # 1060 <_IO_stdin_used+0x70>
c05:   00 
c06:   31 c9                   xor    %ecx,%ecx
c08:   66 0f 6f 2d 60 04 00    movdqa 0x460(%rip),%xmm5        # 1070 <_IO_stdin_used+0x80>
c0f:   00 
c10:   66 0f 6f cc             movdqa %xmm4,%xmm1
c14:   66 44 0f 6f da          movdqa %xmm2,%xmm11
c19:   66 0f 6f 00             movdqa (%rax),%xmm0
c1d:   48 83 c1 01             add    $0x1,%rcx
c21:   48 83 c0 10             add    $0x10,%rax
c25:   49 39 c8                cmp    %rcx,%r8
c28:   66 0f 74 c6             pcmpeqb %xmm6,%xmm0
c2c:   66 0f db c5             pand   %xmm5,%xmm0
c30:   66 0f 64 c8             pcmpgtb %xmm0,%xmm1
c34:   66 0f 6f f8             movdqa %xmm0,%xmm7
c38:   66 0f 60 f9             punpcklbw %xmm1,%xmm7
c3c:   66 0f 68 c1             punpckhbw %xmm1,%xmm0
c40:   66 0f 6f cb             movdqa %xmm3,%xmm1
c44:   66 44 0f 6f d7          movdqa %xmm7,%xmm10
c49:   66 0f 65 cf             pcmpgtw %xmm7,%xmm1
c4d:   66 44 0f 6f c8          movdqa %xmm0,%xmm9
c52:   66 44 0f 61 d1          punpcklwd %xmm1,%xmm10
c57:   66 0f 69 f9             punpckhwd %xmm1,%xmm7
c5b:   66 0f 6f cb             movdqa %xmm3,%xmm1
c5f:   66 0f 65 c8             pcmpgtw %xmm0,%xmm1
c63:   66 45 0f 66 da          pcmpgtd %xmm10,%xmm11
c68:   66 44 0f 61 c9          punpcklwd %xmm1,%xmm9
c6d:   66 0f 69 c1             punpckhwd %xmm1,%xmm0
c71:   66 41 0f 6f ca          movdqa %xmm10,%xmm1
c76:   66 45 0f 6a d3          punpckhdq %xmm11,%xmm10
c7b:   66 41 0f 62 cb          punpckldq %xmm11,%xmm1
c80:   66 41 0f d4 c8          paddq  %xmm8,%xmm1
c85:   66 44 0f 6f c2          movdqa %xmm2,%xmm8
c8a:   66 41 0f d4 ca          paddq  %xmm10,%xmm1
c8f:   66 44 0f 6f d7          movdqa %xmm7,%xmm10
c94:   66 44 0f 66 c7          pcmpgtd %xmm7,%xmm8
c99:   66 41 0f 6a f8          punpckhdq %xmm8,%xmm7
c9e:   66 45 0f 62 d0          punpckldq %xmm8,%xmm10
ca3:   66 45 0f 6f c1          movdqa %xmm9,%xmm8
ca8:   66 41 0f d4 ca          paddq  %xmm10,%xmm1
cad:   66 0f d4 cf             paddq  %xmm7,%xmm1
cb1:   66 0f 6f fa             movdqa %xmm2,%xmm7
cb5:   66 41 0f 66 f9          pcmpgtd %xmm9,%xmm7
cba:   66 44 0f 62 c7          punpckldq %xmm7,%xmm8
cbf:   66 44 0f 6a cf          punpckhdq %xmm7,%xmm9
cc4:   66 0f 6f fa             movdqa %xmm2,%xmm7
cc8:   66 41 0f d4 c8          paddq  %xmm8,%xmm1
ccd:   66 0f 66 f8             pcmpgtd %xmm0,%xmm7
cd1:   66 44 0f 6f c0          movdqa %xmm0,%xmm8
cd6:   66 41 0f d4 c9          paddq  %xmm9,%xmm1
cdb:   66 44 0f 62 c7          punpckldq %xmm7,%xmm8
ce0:   66 0f 6a c7             punpckhdq %xmm7,%xmm0
ce4:   66 41 0f d4 c8          paddq  %xmm8,%xmm1
ce9:   66 0f d4 c8             paddq  %xmm0,%xmm1
ced:   66 44 0f 6f c1          movdqa %xmm1,%xmm8
cf2:   0f 87 18 ff ff ff       ja     c10 <main+0x230>
cf8:   66 0f 73 d9 08          psrldq $0x8,%xmm1
cfd:   4c 89 c9                mov    %r9,%rcx
d00:   66 41 0f d4 c8          paddq  %xmm8,%xmm1
d05:   66 48 0f 7e ca          movq   %xmm1,%rdx
d0a:   48 83 e1 f0             and    $0xfffffffffffffff0,%rcx
d0e:   48 8d 04 0f             lea    (%rdi,%rcx,1),%rax
d12:   4c 01 d2                add    %r10,%rdx
d15:   49 39 c9                cmp    %rcx,%r9
d18:   74 1a                   je     d34 <main+0x354>
d1a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
d20:   31 c9                   xor    %ecx,%ecx
d22:   80 38 3a                cmpb   $0x3a,(%rax)
d25:   0f 94 c1                sete   %cl
d28:   48 83 c0 01             add    $0x1,%rax
d2c:   48 01 ca                add    %rcx,%rdx
d2f:   48 39 c6                cmp    %rax,%rsi
d32:   75 ec                   jne    d20 <main+0x340>
# Area of interest:
d34:   48 83 fa 01             cmp    $0x1,%rdx
d38:   7e 54                   jle    d8e <main+0x3ae>
d3a:   48 8d 35 e7 02 00 00    lea    0x2e7(%rip),%rsi        # 1028 <_IO_stdin_used+0x38>
d41:   48 8d 3d d8 12 20 00    lea    0x2012d8(%rip),%rdi        # 202020 <_ZSt4cerr@@GLIBCXX_3.4>
d48:   e8 33 fc ff ff          callq  980 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
d4d:   48 8b 3c 24             mov    (%rsp),%rdi
d51:   48 83 c3 10             add    $0x10,%rbx
d55:   48 39 df                cmp    %rbx,%rdi
d58:   74 05                   je     d5f <main+0x37f>
d5a:   e8 11 fc ff ff          callq  970 <_ZdlPv@plt>
d5f:   31 c0                   xor    %eax,%eax
d61:   48 8b 5c 24 28          mov    0x28(%rsp),%rbx
d66:   64 48 33 1c 25 28 00    xor    %fs:0x28,%rbx
d6d:   00 00 
d6f:   0f 85 80 00 00 00       jne    df5 <main+0x415>
d75:   48 83 c4 38             add    $0x38,%rsp
d79:   5b                      pop    %rbx
d7a:   5d                      pop    %rbp
d7b:   41 5c                   pop    %r12
d7d:   41 5d                   pop    %r13
d7f:   c3                      retq   
d80:   41 0f b6 04 24          movzbl (%r12),%eax
d85:   88 44 24 10             mov    %al,0x10(%rsp)
d89:   e9 ac fc ff ff          jmpq   a3a <main+0x5a>
d8e:   48 8d 35 a8 02 00 00    lea    0x2a8(%rip),%rsi        # 103d <_IO_stdin_used+0x4d>
d95:   48 8d 3d 84 12 20 00    lea    0x201284(%rip),%rdi        # 202020 <_ZSt4cerr@@GLIBCXX_3.4>
d9c:   e8 df fb ff ff          callq  980 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
da1:   eb aa                   jmp    d4d <main+0x36d>
da3:   48 8d 78 01             lea    0x1(%rax),%rdi
da7:   e8 e4 fb ff ff          callq  990 <_Znwm@plt>
dac:   48 89 6c 24 10          mov    %rbp,0x10(%rsp)
db1:   48 89 04 24             mov    %rax,(%rsp)
db5:   48 89 ea                mov    %rbp,%rdx
db8:   4c 89 e6                mov    %r12,%rsi
dbb:   48 89 c7                mov    %rax,%rdi
dbe:   e8 8d fb ff ff          callq  950 <memcpy@plt>
dc3:   e9 72 fc ff ff          jmpq   a3a <main+0x5a>
dc8:   49 83 c2 01             add    $0x1,%r10
dcc:   e9 5d fd ff ff          jmpq   b2e <main+0x14e>
dd1:   49 83 c2 01             add    $0x1,%r10
dd5:   e9 6c fd ff ff          jmpq   b46 <main+0x166>
dda:   31 d2                   xor    %edx,%edx
ddc:   e9 3f ff ff ff          jmpq   d20 <main+0x340>
de1:   49 83 c2 01             add    $0x1,%r10
de5:   e9 ec fd ff ff          jmpq   bd6 <main+0x1f6>
dea:   48 89 c7                mov    %rax,%rdi
ded:   45 31 d2                xor    %r10d,%r10d
df0:   e9 eb fd ff ff          jmpq   be0 <main+0x200>
df5:   e8 a6 fb ff ff          callq  9a0 <__stack_chk_fail@plt>
dfa:   48 8d 3d f7 01 00 00    lea    0x1f7(%rip),%rdi        # ff8 <_IO_stdin_used+0x8>
e01:   e8 3a fb ff ff          callq  940 <_ZSt19__throw_logic_errorPKc@plt>
e06:   4c 89 e8                mov    %r13,%rax
e09:   eb aa                   jmp    db5 <main+0x3d5>
e0b:   48 8b 3c 24             mov    (%rsp),%rdi
e0f:   48 83 c3 10             add    $0x10,%rbx
e13:   48 89 c5                mov    %rax,%rbp
e16:   48 39 df                cmp    %rbx,%rdi
e19:   74 05                   je     e20 <main+0x440>
e1b:   e8 50 fb ff ff          callq  970 <_ZdlPv@plt>
e20:   48 89 ef                mov    %rbp,%rdi
e23:   e8 98 fb ff ff          callq  9c0 <_Unwind_Resume@plt>
e28:   0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
e2f:   00 

对于感兴趣的人,您可以通过使用带符号的数字来解决这个问题,如:

#include <type_traits>
...
if(static_cast<std::make_signed_t<decltype(colons)>>(colons) >= 2LL)
...

或将if()语句包装在#pragma周围,如下所示:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-overflow"
if(colons >= 2LL)
#pragma GCC diagnostic pop

但这显然不是这里的问题。

std::count定义为:https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/libstdc%2B%2B-v3/include/bits/stl_algo.h#L4045

/**
*  @brief Count the number of copies of a value in a sequence.
*  @ingroup non_mutating_algorithms
*  @param  __first  An input iterator.
*  @param  __last   An input iterator.
*  @param  __value  The value to be counted.
*  @return   The number of iterators @c i in the range @p [__first,__last)
*  for which @c *i == @p __value
*/
template<typename _InputIterator, typename _Tp>
_GLIBCXX20_CONSTEXPR
inline typename iterator_traits<_InputIterator>::difference_type
count(_InputIterator __first, _InputIterator __last, const _Tp& __value)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_function_requires(_EqualOpConcept<
typename iterator_traits<_InputIterator>::value_type, _Tp>)
__glibcxx_requires_valid_range(__first, __last);
return std::__count_if(__first, __last,
__gnu_cxx::__ops::__iter_equals_val(__value));
}

然后https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/libstdc%2B%2B-v3/include/bits/stl_algobase.h#L2118:

template<typename _InputIterator, typename _Predicate>
_GLIBCXX20_CONSTEXPR
typename iterator_traits<_InputIterator>::difference_type
__count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
{
typename iterator_traits<_InputIterator>::difference_type __n = 0;
for (; __first != __last; ++__first)
if (__pred(__first))
++__n;
return __n;
}

__niterator_traits<_InputIterator>::difference_type,ptrdiff_t是有符号类型。执行++__n可能导致有符号类型溢出,但这是未定义的行为。因此,std::count()不能返回负,因为这将是未定义的行为。因为不能返回负数,编译器可以使用jle,数字不能是负数

最新更新