@@ -1,18 +1,18 @@
|
||||
# Overflow
|
||||
|
||||
The factorial of a number grows quite fast.
|
||||
The factorial of a number grows quite fast.\
|
||||
For example, the factorial of 20 is 2,432,902,008,176,640,000. That's already bigger than the maximum value for a
|
||||
32-bit integer, 2,147,483,647.
|
||||
|
||||
When the result of an arithmetic operation is bigger than the maximum value for a given integer type,
|
||||
we are talking about **an integer overflow**.
|
||||
|
||||
Integer overflows are an issue because they violate the contract for arithmetic operations.
|
||||
Integer overflows are an issue because they violate the contract for arithmetic operations.\
|
||||
The result of an arithmetic operation between two integers of a given type should be another integer of the same type.
|
||||
But the _mathematically correct result_ doesn't fit into that integer type!
|
||||
|
||||
> If the result is smaller than the minimum value for a given integer type, we refer to the event as **an integer
|
||||
> underflow**.
|
||||
> underflow**.\
|
||||
> For brevity, we'll only talk about integer overflows for the rest of this section, but keep in mind that
|
||||
> everything we say applies to integer underflows as well.
|
||||
>
|
||||
@@ -32,7 +32,7 @@ is not Rust's solution to the integer overflow problem.
|
||||
|
||||
## Alternatives
|
||||
|
||||
Since we ruled out automatic promotion, what can we do when an integer overflow occurs?
|
||||
Since we ruled out automatic promotion, what can we do when an integer overflow occurs?\
|
||||
It boils down to two different approaches:
|
||||
|
||||
- Reject the operation
|
||||
@@ -40,13 +40,13 @@ It boils down to two different approaches:
|
||||
|
||||
### Reject the operation
|
||||
|
||||
This is the most conservative approach: we stop the program when an integer overflow occurs.
|
||||
This is the most conservative approach: we stop the program when an integer overflow occurs.\
|
||||
That's done via a panic, the mechanism we've already seen in the ["Panics" section](04_panics.md).
|
||||
|
||||
### Come up with a "sensible" result
|
||||
|
||||
When the result of an arithmetic operation is bigger than the maximum value for a given integer type, you can
|
||||
choose to **wrap around**.
|
||||
choose to **wrap around**.\
|
||||
If you think of all the possible values for a given integer type as a circle, wrapping around means that when you
|
||||
reach the maximum value, you start again from the minimum value.
|
||||
|
||||
@@ -69,14 +69,14 @@ You may be wondering—what is a profile setting? Let's get into that!
|
||||
A [**profile**](https://doc.rust-lang.org/cargo/reference/profiles.html) is a set of configuration options that can be
|
||||
used to customize the way Rust code is compiled.
|
||||
|
||||
Cargo provides two built-in profiles: `dev` and `release`.
|
||||
Cargo provides two built-in profiles: `dev` and `release`.\
|
||||
The `dev` profile is used every time you run `cargo build`, `cargo run` or `cargo test`. It's aimed at local
|
||||
development,
|
||||
therefore it sacrifices runtime performance in favor of faster compilation times and a better debugging experience.
|
||||
therefore it sacrifices runtime performance in favor of faster compilation times and a better debugging experience.\
|
||||
The `release` profile, instead, is optimized for runtime performance but incurs longer compilation times. You need
|
||||
to explicitly request via the `--release` flag—e.g. `cargo build --release` or `cargo run --release`.
|
||||
|
||||
> "Have you built your project in release mode?" is almost a meme in the Rust community.
|
||||
> "Have you built your project in release mode?" is almost a meme in the Rust community.\
|
||||
> It refers to developers who are not familiar with Rust and complain about its performance on
|
||||
> social media (e.g. Reddit, Twitter, etc.) before realizing they haven't built their project in
|
||||
> release mode.
|
||||
@@ -90,12 +90,12 @@ By default, `overflow-checks` is set to:
|
||||
- `true` for the `dev` profile
|
||||
- `false` for the `release` profile
|
||||
|
||||
This is in line with the goals of the two profiles.
|
||||
`dev` is aimed at local development, so it panics in order to highlight potential issues as early as possible.
|
||||
This is in line with the goals of the two profiles.\
|
||||
`dev` is aimed at local development, so it panics in order to highlight potential issues as early as possible.\
|
||||
`release`, instead, is tuned for runtime performance: checking for overflows would slow down the program, so it
|
||||
prefers to wrap around.
|
||||
|
||||
At the same time, having different behaviours for the two profiles can lead to subtle bugs.
|
||||
At the same time, having different behaviours for the two profiles can lead to subtle bugs.\
|
||||
Our recommendation is to enable `overflow-checks` for both profiles: it's better to crash than to silently produce
|
||||
incorrect results. The runtime performance hit is negligible in most cases; if you're working on a performance-critical
|
||||
application, you can run benchmarks to decide if it's something you can afford.
|
||||
@@ -107,4 +107,4 @@ application, you can run benchmarks to decide if it's something you can afford.
|
||||
## Further reading
|
||||
|
||||
- Check out ["Myths and legends about integer overflow in Rust"](https://huonw.github.io/blog/2016/04/myths-and-legends-about-integer-overflow-in-rust/)
|
||||
for an in-depth discussion about integer overflow in Rust.
|
||||
for an in-depth discussion about integer overflow in Rust.
|
||||
|
||||
Reference in New Issue
Block a user