为什么在调试模式下重复乘法会因溢出而崩溃,而在发布模式下它只输出零?

Why does repeated multiplication panic due to overflow in debug mode, when it outputs only zeroes in release mode?

我写了这段代码:

fn main() {
    let mut k: i64 = 1;
    loop {
        k = k * 10;
        println!("cool {}", k);
    }
}

如果我 运行 cargo run 我得到:

cool 10
cool 100
cool 1000
cool 10000
cool 100000
cool 1000000
cool 10000000
cool 100000000
cool 1000000000
cool 10000000000
cool 100000000000
cool 1000000000000
cool 10000000000000
cool 100000000000000
cool 1000000000000000
cool 10000000000000000
cool 100000000000000000
cool 1000000000000000000
thread 'main' panicked at 'attempt to multiply with overflow', src/main.rs:4:14
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

但是如果我 运行 cargo build --release 之后的可执行文件(在发布目录中),我会得到一个无限循环:

cool 0
cool 0
cool 0
cool 0
cool 0
cool 0
...

我知道“在发布版本中,操作环绕:它产生的值等于数学上正确的结果对值的范围取模”,但我不太明白为什么我没有得到“0”在调试模式下。

我也试过:

fn main() {
    let mut k: i32 = 1;
    loop {
        k = k * 10;
        println!("cool {}", k);
        k.checked_mul(10).expect("overflow!");
    }
}

并得到:

cool 10
cool 100
cool 1000
cool 10000
cool 100000
cool 1000000
cool 10000000
cool 100000000
cool 1000000000
thread 'main' panicked at 'overflow!', src/main.rs:6:27
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

为什么?

实际上释放模式下的输出是这样的:

cool 10
cool 100
cool 1000
cool 10000
cool 100000
cool 1000000
cool 10000000
cool 100000000
cool 1000000000
cool 10000000000
cool 100000000000
cool 1000000000000
cool 10000000000000
cool 100000000000000
cool 1000000000000000
cool 10000000000000000
cool 100000000000000000
cool 1000000000000000000
cool -8446744073709551616
cool 7766279631452241920
cool 3875820019684212736
cool 1864712049423024128
cool 200376420520689664
cool 2003764205206896640
cool 1590897978359414784
cool -2537764290115403776
cool -6930898827444486144
cool 4477988020393345024
cool 7886392056514347008
cool 5076944270305263616
cool -4570789518076018688
cool -8814407033341083648
cool 4089650035136921600
cool 4003012203950112768
cool 3136633892082024448
cool -5527149226598858752
cool 68739955140067328
cool 687399551400673280
cool 6873995514006732800
cool -5047021154770878464
cool 4870020673419870208
cool -6640025486929952768
cool 7386721425538678784
cool 80237960548581376
cool 802379605485813760
cool 8023796054858137600
cool 6450984253743169536
cool 9169610316303040512
cool -537617205517352960
cool -5376172055173529600
cool 1578511669393358848
cool -2661627379775963136
cool -8169529724050079744
cool -7908320945662590976
cool -5296233161787703296
cool 2377900603251621888
cool 5332261958806667264
cool -2017612633061982208
cool -1729382256910270464
cool 1152921504606846976
cool -6917529027641081856
cool 4611686018427387904
cool -9223372036854775808
cool 0
cool 0
cool 0
cool 0
cool 0
cool 0
cool 0
...

在调试模式下程序只是恐慌,但在发布模式下没有恐慌。如您所见,在某个时刻开始发生溢出。然后在稍后的阶段 k 变成 0 之后它当然会保持 0

您可能错过了第一行而只看到了最后一行?

顺便说一句,为了更好地理解我们如何得到零,查看 k 的二进制表示可能会有用,所以让我们稍微更改一下打印行:

println!("cool {k:>22}  {k:>64b}");

现在输出变为:

cool                     10                                                              1010
cool                    100                                                           1100100
cool                   1000                                                        1111101000
cool                  10000                                                    10011100010000
cool                 100000                                                 11000011010100000
cool                1000000                                              11110100001001000000
cool               10000000                                          100110001001011010000000
cool              100000000                                       101111101011110000100000000
cool             1000000000                                    111011100110101100101000000000
cool            10000000000                                1001010100000010111110010000000000
cool           100000000000                             1011101001000011101101110100000000000
cool          1000000000000                          1110100011010100101001010001000000000000
cool         10000000000000                      10010001100001001110011100101010000000000000
cool        100000000000000                   10110101111001100010000011110100100000000000000
cool       1000000000000000                11100011010111111010100100110001101000000000000000
cool      10000000000000000            100011100001101111001001101111110000010000000000000000
cool     100000000000000000         101100011010001010111100001011101100010100000000000000000
cool    1000000000000000000      110111100000101101101011001110100111011001000000000000000000
cool   -8446744073709551616  1000101011000111001000110000010010001001111010000000000000000000
cool    7766279631452241920   110101111000111010111100010110101100011000100000000000000000000
cool    3875820019684212736    11010111001001101011011100010111011110101000000000000000000000
cool    1864712049423024128     1100111100000110010011011101010110010010000000000000000000000
cool     200376420520689664        1011000111111000010100101011110110100000000000000000000000
cool    2003764205206896640     1101111001110110011001110110110100001000000000000000000000000
cool    1590897978359414784     1011000010100000000010100100001001010000000000000000000000000
cool   -2537764290115403776  1101110011001000000011001101001011100100000000000000000000000000
cool   -6930898827444486144  1001111111010000100000000011110011101000000000000000000000000000
cool    4477988020393345024    11111000100101000000100110000100010000000000000000000000000000
cool    7886392056514347008   110110101110010000101111100101010100000000000000000000000000000
cool    5076944270305263616   100011001110100111011011110101001000000000000000000000000000000
cool   -4570789518076018688  1100000010010001010010110010011010000000000000000000000000000000
cool   -8814407033341083648  1000010110101100111011111000000100000000000000000000000000000000
cool    4089650035136921600    11100011000001010110110000101000000000000000000000000000000000
cool    4003012203950112768    11011110001101100011100110010000000000000000000000000000000000
cool    3136633892082024448    10101110000111100011111110100000000000000000000000000000000000
cool   -5527149226598858752  1011001101001011100111110001000000000000000000000000000000000000
cool      68739955140067328          11110100001101101010000000000000000000000000000000000000
cool     687399551400673280      100110001010001000100100000000000000000000000000000000000000
cool    6873995514006732800   101111101100101010101101000000000000000000000000000000000000000
cool   -5047021154770878464  1011100111110101011000010000000000000000000000000000000000000000
cool    4870020673419870208   100001110010101110010100000000000000000000000000000000000000000
cool   -6640025486929952768  1010001111011001111001000000000000000000000000000000000000000000
cool    7386721425538678784   110011010000010111010000000000000000000000000000000000000000000
cool      80237960548581376         100011101000100000000000000000000000000000000000000000000
cool     802379605485813760      101100100010101000000000000000000000000000000000000000000000
cool    8023796054858137600   110111101011010010000000000000000000000000000000000000000000000
cool    6450984253743169536   101100110000110100000000000000000000000000000000000000000000000
cool    9169610316303040512   111111101000001000000000000000000000000000000000000000000000000
cool    -537617205517352960  1111100010001010000000000000000000000000000000000000000000000000
cool   -5376172055173529600  1011010101100100000000000000000000000000000000000000000000000000
cool    1578511669393358848     1010111101000000000000000000000000000000000000000000000000000
cool   -2661627379775963136  1101101100010000000000000000000000000000000000000000000000000000
cool   -8169529724050079744  1000111010100000000000000000000000000000000000000000000000000000
cool   -7908320945662590976  1001001001000000000000000000000000000000000000000000000000000000
cool   -5296233161787703296  1011011010000000000000000000000000000000000000000000000000000000
cool    2377900603251621888    10000100000000000000000000000000000000000000000000000000000000
cool    5332261958806667264   100101000000000000000000000000000000000000000000000000000000000
cool   -2017612633061982208  1110010000000000000000000000000000000000000000000000000000000000
cool   -1729382256910270464  1110100000000000000000000000000000000000000000000000000000000000
cool    1152921504606846976     1000000000000000000000000000000000000000000000000000000000000
cool   -6917529027641081856  1010000000000000000000000000000000000000000000000000000000000000
cool    4611686018427387904   100000000000000000000000000000000000000000000000000000000000000
cool   -9223372036854775808  1000000000000000000000000000000000000000000000000000000000000000
cool                      0                                                                 0
cool                      0                                                                 0
cool                      0                                                                 0
cool                      0                                                                 0