Related Tags

rust
overflow

# How to detect overflow without crashing the program in Rust

Educative Team

### Overview

In computing, an overflow error occurs when a program encounters a number, value, or variable that exceeds the program’s ability: it cannot handle the computation result. This type of error is common in programming, especially when working with integers or other numerical variables.

### Introduction

We get an overflow error when a computation executes, and the system cannot correctly handle and store it due to the computation’s result exceeding the system’s capabilities. For example, running an infinite loop, making recursive calls without a base case, etc.

There are many ways to handle overflow, but now we will discuss only a few of them: checked_sub() and checked_div(). Both methods perform the calculations in an isolated environment and examine the output results. If the calculations exceed the computer’s ability, both methods terminate the calculations and return NULL. In contrast, if the calculations end with an appropriate output, then both methods return the output of the calculations.

### The checked_sub() method

#### Syntax

let <resultant> = <variable1>.checked_sub(<variable2>);


#### Result

This function can have only two types of output results:

1. None: This means an overflow has occurred, and the calculations have stopped.
2. Result of the calculations, which means that the overflow did not occur.

So the checked_sub() function has the following functionality:

$resultant = variable1 - variable2$

Let’s look at it in the example below.

#### Example

// Main function
fn main() {
let variable1: i16 = 32767;
let variable2: i16 = 0;
let resultant = variable1.checked_sub(variable2);
println!("Max +ve limit of datatype (i16) is: {}",i16::MAX);
println!("Output of checked_sub() is: {:?}",resultant);
assert_eq!(resultant, None,"Overflow did not Occur(^_^)");
println!("Overflow Occured(-_-)");
}
Inefficient way to handle overflow

#### Explanation

Note: We can see that this program behaves abnormally because it only works normally when an overflow arises. It displays an error when an overflow does not occur. This is happening because we are using the assert_eq! command, which displays a note whenever its input arguments get matched.

• In lines 3-4, we declare two variables of type i16.
• In line 5, we implement the checked_sub() method to observe the future output when we subtract variable2 from variable1.
• In line 6, we print out the maximum positive limit of the i16 data type.
• In line 7, we print out the resultant of the checked_sub() method.
• In line 8, we compare whether result of checked_sub() method (resultant) is equal to None. If it is, it means that an overflow has occurred.

To remove the overflow error, change the value of variable2 from 0 to any negative number within the range $-1$ to $-32767$.

### The checked_div() method

#### Syntax

let <resultant> = <variable1>.checked_div(<variable2>);


#### Result

This function can have only two types of output results:

• None: This means that an overflow has occurred, and the calculations have stopped.
• Result of the calculations, which means that the overflow did not occur.

So the checked_div() function has the following functionality:

$resultant = variable1/variable2$

Let’s look at it in the example below.

#### Example 2

Now, we are going to implement checked_div() method to handle overflow in an improved way.

// Main function
fn main()
{
let val1 = u32::max_value();
let val2 = 0;

// Match function
match val1.checked_div(val2) {
None => {
println!("Max limit of u16 is: {}",val1);
println!("As we know that {}/{} = Inf.", val1, val2);
println!("Output of checked_div() is: Inf.");
println!("overflow! (-__-)");
}
Some(ans) => {
println!("Max limit of datatype (u16) is: {}",val1);
println!("As we know that {}/{} = {}", val1, val2, ans);
println!("Output of checked_div() is: {:?}",ans);
println!("No Overflow!!! program is running fine (^__^)");
}

};
}

Efficient way to handle overflow

Note: An overflow will occur if we use 0 instead of 1 as the value of val2.

• In lines 3-4, we declare the variables val1 and val2.
• In line 6, we implement the match() function, a conditional statement whose output is dependent on the nature of its input because it matches up its value to the value of each case. If a match is found, the corresponding piece of code executes. Now its input is the result of the checked_div() method.

RELATED TAGS

rust
overflow