为什么在调试模式下重复乘法会因溢出而崩溃,而在发布模式下它只输出零?
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
我写了这段代码:
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