Return to SwATips | pdf |
In a recent code review, one of our customers were marked for being sloppy with catch-all exceptions (CWE-396), which is sometimes an indicator of poorly designed program flow. To fix this, the developers changed the catch blocks to something like the one in Listing 1.
The intent of a “when” clause in an exception is for situations where the exception may have an error code. For example, a SqlException may return different codes that can be used to differentiate their catch blocks and clean up a failed state. So how does the code in Listing 1 differ from the code in Listing 2?
While both blocks of code achieve the same result, the generated code to catch the exception in Listing 1 has twelve times as many instructions to execute. The .NET Intermediate Language (IL) is very different between the two implementations. The “when” clause creates what the IL defines as a filter block and instantiates a structure similar to a truth stack. This additional structure and the extra operations on it reduce performance and add unnecessary bloat to the software. The generated IL can be compared in Listings 3 and 4. The IL was created in optimized Release mode.
This leads to another question: what’s the most optimal way to catch several types of exceptions? The most optimal way is to catch the general exception, then use polymorphism to operate on it (code in Listing 5). The IL code adds a single comparison for each conditional in an if statement and avoids the overhead incurred by the when clause’s filter block. Note that most scanning tools and style checkers will identify Listing 5 as a catch for the generic exception, but this should be marked as a false positive if the handler appropriately determines the failure scenarios for the appropriate exception types. The IL code for Listing 5 up to the first exception type is shown in Listing 6. Please also realize that such minimal performance gains should not be interpreted as a reason to violate a consistent standard already established in a code base.
When performance is a primary concern, developers should include comments that indicate their consideration of exceptional cases in generic catch blocks. Validators should watch for these comments to help them mark the generic exception catches as false positives.
Jon Hood, ed. SwATips. https://www.SwATips.com/.