Main Content

AUTOSAR C++14 Rule M15-1-3

An empty throw (throw;) shall only be used in the compound statement of a catch handler

Description

Rule Definition

An empty throw (throw;) shall only be used in the compound statement of a catch handler.

Rationale

When you use an empty throw statement (throw;), the compiler checks if an exception object is present in the current scope. If the current scope contains an exception object, the compiler raises a temporary object containing the current exception. If the current scope does not contain an exception objects, the compiler invokes std::terminate() implicitly. The function std::terminate() terminates the program execution in an implementation-defined manner. That is, the exact process of program termination depends on the software and hardware that you are using. For instance, std:terminate() might invoke std::abort() to abnormally abort the execution without unwinding the stack, leading to resource leak and security vulnerabilities.

The best practice is to use an empty throw statement only in the catch block of a try-catch construct, which enables you to spread the handling of an exception across multiple catch blocks. Avoid using empty throw statements in scopes that might not contain an exception.

Polyspace Implementation

Polyspace® flags an empty throw statement if it is not within a catch block.

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 <iostream>       
#include <typeinfo>       
#include <exception>      

void handleException()//function to handle all exception
{
	try {
		throw; // Noncompliant
	}
	catch (std::bad_cast& e) {
		//...Handle bad_cast...
	}
	catch (std::bad_alloc& e) {
		//...Handle bad_alloc...
	}
	catch(...){
		//...Handle other exceptions
	}
}

void f()
{
	try {
		//...something that might throw...
	}
	catch (...) {
		handleException();
	}
}

In this example, the function handleException() raises the current exception by using an empty throw statement, and then directs it to the appropriate catch block. This method of delegating the exception handling works as intended only when the function handleException() is called from within a catch block. The empty throw statement might cause abrupt termination of the program if the function is called in any other scope that does not contain an exception. Polyspace flags the empty throw statement.

#include <iostream>       
#include <typeinfo>       
#include <exception> 
void foo()//function to handle all exception
{
	try {
		//...
	}
	catch (std::bad_cast& e) {
		//...Handle bad_cast...
	}
	catch (std::bad_alloc& e) {
		//...Handle bad_alloc...
	}
	catch(std::exception& e){
		//...Handle std::exceptions
		// if exception cannot be handled
		// throw it again
		throw;//Compliant
	}
}

int main(){
	try{
		foo();
	}
	catch(...){
		
	}
}

This example shows a compliant use of an empty throw statement. The function foo contains a try-catch construct that handles specific exceptions. If the raised exception cannot be handled, foo raises the exception again as an unhandled exception by using an empty throw statement. In main, the function foo is invoked and any unhandled exception arising from foo is handled in a generic catch(...) block. By using the empty throw statement, the handling of the exception is spread across the catch blocks of foo and main. In this case, the empty throw statement is executed only when there is an exception in the same scope because it is within a catch block. Polyspace does not flag it.

Check Information

Group: Exception Handling
Category: Required, Automated

Version History

Introduced in R2019a