在这种情况下,我得到这个错误:
错误:假设在简化条件
时没有发生符号溢出
我看了看汇编和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;
}
__n
是iterator_traits<_InputIterator>::difference_type
,ptrdiff_t
是有符号类型。执行++__n
可能导致有符号类型溢出,但这是未定义的行为。因此,std::count()
不能返回负,因为这将是未定义的行为。因为不能返回负数,编译器可以使用jle
,数字不能是负数