rspec/rules/S1035/cfamily/rule.adoc
2023-07-28 13:10:31 +02:00

102 lines
3.4 KiB
Plaintext

== Why is this an issue?
When an exception is a pointer, it is difficult for the code that catches the exception to determine whether or not it needs to delete the pointed-to object.
It is even more complicated than a traditional manual memory management scenario because the `throw` and the corresponding `catch` can be far apart.
== How to fix it
Throwing by value is more straightforward and less error-prone than using a pointer as an exception object.
=== Code examples
==== Noncompliant code example
[source,cpp,diff-id=1,diff-type=noncompliant]
----
std::out_of_range globalException("Index too high");
void fn(int i) {
// In this situation, the developer writing the "catch" has no way of knowing if the object pointed to by
// the exception should be deleted or not
if (i > 10) {
throw (&globalException); // Noncompliant: the catch is supposed not to delete the pointer
} else {
throw (new std::out_of_range{"Invalid index"}); // Noncompliant: the catch is supposed to delete the pointer
}
}
----
==== Compliant solution
[source,cpp,diff-id=1,diff-type=compliant]
----
std::out_of_range globalException("Index too high");
void fn(int i) {
if (i > 10) {
throw (globalException); // Compliant: it throws a copy of the global variable
} else {
throw (std::out_of_range{"Invalid index"}); // Compliant: it throws a new object
}
}
----
== Resources
=== External coding guidelines
* MISRA {cpp} 2008, 15-0-2 - An exception object should not have pointer type.
=== Related rules
* S1044 - Exception classes should be caught by reference
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Throw the exception by value.
'''
== Comments And Links
(visible only on this page)
=== on 14 Oct 2014, 17:51:53 Ann Campbell wrote:
\[~samuel.mercier] please correct the following
* Add a See section to the description listing the appropriate MISRA number
* Fill in Applicability.
* Make sure the appropriate MISRA C and MISRA {cpp} fields on the references tab are filled in
=== on 14 Oct 2014, 18:34:18 Ann Campbell wrote:
Also [~samuel.mercier] I don't think Maintainability is appropriate here. The risks are
* both caller and callee destroy the object - undefined behavior (likely runtime crash)
* neither caller nor callee destroys the object - memory leak
Since the worse outcome is a crash, I would associate this to Reliability
=== on 14 Oct 2014, 20:15:26 Freddy Mallet wrote:
And if this is associated to the Reliability category, then the tag 'pitfall' should be replaced by 'bug'
=== on 17 Oct 2014, 09:12:45 Samuel Mercier wrote:
\[~ann.campbell.2] caller cannot destroys the object, unless it also catches the exception it has thrown. But I agree about the memory leak, so I updated to Reliablity / Exception handling
=== on 20 Apr 2015, 10:00:42 Evgeny Mandrikov wrote:
\[~ann.campbell.2] this rule has tag "bug" and severity "critical", but not enabled by default. Is it on purpose?
=== on 20 Apr 2015, 10:09:05 Ann Campbell wrote:
It was on purpose [~evgeny.mandrikov], since this strikes me as potentially an issue of house style. If you think it is not, feel free to set it on by default.
=== on 11 May 2015, 20:24:44 Evgeny Mandrikov wrote:
\[~ann.campbell.2] I don't see any valid reason for catching/throwing an exception by pointer, , while opposite is highly recommended, so don't see any reason to not activate this rule by default.
endif::env-github,rspecator-view[]