Main Content

MISRA C++:2023 Rule 18.3.1

There should be at least one exception handler to catch all otherwise unhandled exceptions

Since R2024b

Description

Rule Definition

There should be at least one exception handler to catch all otherwise unhandled exceptions.

Rationale

When an exception remains unhandled, the compiler might invoke the function std::terminate(), which terminates the program abruptly. The abrupt termination does not invoke any exit handlers, does not call the destructors of the constructed objects, and does not unwind the stack.

Exceptions that are unhandled might result in issues such as memory leaks, security vulnerability, and other unintended behaviors. Poorly designed exception handling process might make your program vulnerable to denial-of-service attacks.

Design the exception handling in your code to handle expected and unexpected exceptions. Call functions that are not noexcept in try blocks. Handle the exceptions that these functions might raise by using matching catch() blocks. Include a catch-all block in main() to handle unexpected exceptions.

Polyspace Implementation

Polyspace® reports a violation when a function that is called in main() raises an exception and the exception is not handled. Polyspace highlights the location in the function body where the unhandled exception is raised and flags the call to the function in main(). For instance:

void foo(){
    throw std::exception(); //Uncaught exception
}
int main(){
    foo(); //Defect
    return 1;
} 
Polyspace does not report a violation when an std::bad_alloc raised by a new operator remains unhandled.

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#include <exception>
#include <stdexcept>

int flag();

void foo() {
	if (flag()==0) {
		//....
		throw std::exception();     
	}
}

void bar() {
	if (flag()!=0 & flag()!=1) {
		throw std::logic_error("Error"); 
	}
}



void fubar() {
	foo();            
}

int main() {
	foo(); // Defect
	bar(); // Defect 
	fubar(); // Defect

}

In this exception, the functions foo() and bar() raise exceptions that are not handled. The function fubar() raises an unhandled exception by calling foo(). These functions are invoked in main(). Because these functions raise exceptions that are unhandled and are called from the main() function, Polyspace flags the calls to these functions in main.

Correction — Handle all exceptions

To resolve this defect, handle all exceptions in your code. For instance, in the main() function, call the exception raising function in a try block and handle the exception by using a series of catch() blocks, including a catch(...) block.

#include <exception>
#include <stdexcept>

int flag();

void foo() {
	if (flag()==0) {
		//....
		throw std::exception();     
	}
}

void bar() {
	if (flag()!=0 & flag()!=1) {
		throw std::logic_error("bla"); 
	}
}



void fubar() {
	foo();            
}

int main() {
	try{
	foo(); // Defect
	bar(); // Defect 
	fubar(); // Defect
	}catch(std::logic_error& e){
		//...
	}catch(std::exception& e){
		//...
	}catch(...){
		//..
	}

}

Check Information

Group: Exception Handling
Category: Advisory

Version History

Introduced in R2024b