
...
The variable declared by the exception-declaration, of type cv
T
or cvT&
, is initialized from the exception object, of typeE
, as follows:
— ifT
is a base class ofE
, the variable is copy-initialized from the corresponding base class subobject of the exception object;
— otherwise, the variable is copy-initialized from the exception object.
Because the variable declared by the exception-declaration is copy-initialized, it is possible to slice the exception object as part of the copy operation, losing valuable exception information and leading to incorrect error recovery. For more information about object slicing, see OOP51-CPP. Do not slice derived objects. Further, if the copy constructor of the exception object throws an exception, the copy initialization of the exception-declaration object results in undefined behavior. (See ERR60-CPP. Exception objects must be nothrow copy constructible for more information.)
Always catch exceptions by lvalue reference unless the type is a trivial type. For reference, the C++ Standard, [basic.types], paragraph 9 [ISO/IEC 14882-2014], defines trivial types as the following:
Arithmetic types, enumeration types, pointer types, pointer to member types,
std::nullptr_t
, and cv-qualified versions of these types are collectively called scalar types.... Scalar types, trivial class types, arrays of such types and cv-qualified versions of these types are collectively called trivial types.
...
Object slicing can result in abnormal program execution. This generally is not a problem for exceptions, but it can lead to unexpected behavior depending on the assumptions made by the exception handler.
Rule | Severity | Likelihood |
---|
Detectable | Repairable | Priority | Level |
---|---|---|---|
ERR61-CPP | Low | Unlikely | Yes |
No |
P2 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| catch-class-by-value | Fully checked | ||||||
Axivion Bauhaus Suite |
| CertC++-ERR61 | |||||||
|
| Checked by clang-tidy ; also checks for VOID ERR09-CPP. Throw anonymous temporaries by default | |||||||
CodeSonar |
| LANG.STRUCT.EXCP.CATCH LANG.STRUCT.EXCP.THROW | Use of catch Use of throw | ||||||
Helix QAC |
| C++4031 | |||||||
Klocwork |
| MISRA.CATCH.BY_VALUE | |||||||
LDRA tool suite |
| 455 S | Fully implemented | ||||||
Parasoft C/C++test |
| CERT_CPP-ERR61-a | A class type exception shall always be caught by reference | ||||||
Polyspace Bug Finder |
| CERT C++: ERR61-CPP | Checks for exception object initialized by copy in catch statement (rule fully covered) | ||||||
PVS-Studio |
| V746, V816 | |||||||
RuleChecker |
| catch-class-by-value | Fully checked | ||||||
SonarQube C/C++ Plugin |
| S1044 |
Related Vulnerabilities
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
...
This rule is a subset of OOP51-CPP. Do not slice derived objects.
Bibliography
[ISO/IEC 14882-2014] | Subclause 3.9, "Types" |
[MISRA 2008] | Rule 15-3-5 |
...
...