...
The variable declared by the exception-declaration, of type cv
Tor cvT&, is initialized from the exception object, of typeE, as follows:
— ifTis 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 | RepairableRemediation Cost | Priority | Level |
|---|---|---|---|---|---|---|
ERR61-CPP | Low | Unlikely | Yes | NoLow | P3 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) | PRQA QA-C++ | | Include Page | | PRQA QA-C++_V | PRQA QA-C++_V | 4031||||||
| PVS-Studio |
| V746, V816 | ||||||||||||
| RuleChecker |
| catch-class-by-value | Fully checked | |||||||||||
| SonarQube C/C++ Plugin |
| S1044 |
...