Main Content

AUTOSAR C++14 Rule M15-3-3

Handlers of a function-try-block implementation of a class constructor or destructor shall not reference non-static members from this class or its bases

Description

Rule Definition

Handlers of a function-try-block implementation of a class constructor or destructor shall not reference non-static members from this class or its bases.

Rationale

The handler catch blocks of a function try block handle exception that are raised from the body of the function and the initializer list. When used in class constructors and destructors, these catch blocks might handle exceptions that arise during the creation or destruction of the class nonstatic members. That is, the catch blocks might be executed before or after the lifetime of the nonstatic members of a class. If the nonstatic members of a class are accessed in such catch blocks, the compiler might attempt to access objects that are not created yet or already deleted, which is undefined behavior. For instance:

class C{
	
	private:
	int* inptr_x;
	public:
	C() try: inptr_x(new int){}
	catch(...){
		intptr_x = nullptr;
		//...
	}
};
Here, the constructor of C is implemented by using a function try block to handle any exception arising from the memory allocation operation in the initializer list. In the catch block of this function-try block, the class member C.intptr_x is accessed. The catch block executes when the memory allocation for intptr_x failed. That is, the catch block attempts to access the member before its lifetime, which is undefined behavior.

To avoid undefined behavior, avoid using the nonstatic data members or base classes of an object in the catch block of the function-try-block implementation of its constructors and destructor.

Polyspace Implementation

If a statement in the catch block of a constructor or destructor function-try block accesses any of these, Polyspace® flags the statement:

  • The nonstatic members of the object

  • The base classes of the object

  • The nonstatic members of the base classes

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<cstdint>
class B
{
public:
	B ( ) try: x(0){/*...*/}
	catch ( ... )
	{
		if ( 0 == x ){/*...*/}  //Noncompliant
		//...
	}
	~B ( ) try{/*...*/}
	catch ( ... )
	{
		if ( 0 == x ){/*...*/} //Noncompliant
		//...
		else if (sb == 1){/*...*/} //Compliant
		//....	
	}
public:
	static int32_t sb;
protected:
	int32_t x;
};

class D : public B
{
public:
	D ( ) try: B(),y{0}{/*...*/}
	catch ( ... )
	{
		if ( 0 == x ){/*...*/}  //Noncompliant
		//...
		else if (y == 1){/*...*/}   //Noncompliant
		//...
	}
	~D ( )try {/*...*/}
	catch ( ... )
	{
		if ( 0 == x ) {/*...*/} //Noncompliant
		//...
	}
protected:
	int32_t y;
};

In this example, the constructors and destructors of B and D are implemented by using function-try blocks. The catch blocks of these function-try blocks access the nonstatic members of the class and its base class. Polyspace flags accessing these nonstatic members in the catch blocks. Because the lifetime of static members is greater than the lifetime of the object itself, Polyspace does not flag accessing static objects in these catch blocks.

Check Information

Group: Exception Handling
Category: Required, Automated

Version History

Introduced in R2019a