|
| 1 | +.. title:: clang-tidy - bugprone-empty-catch |
| 2 | + |
| 3 | +bugprone-empty-catch |
| 4 | +==================== |
| 5 | + |
| 6 | +Detects and suggests addressing issues with empty catch statements. |
| 7 | + |
| 8 | +.. code-block:: c++ |
| 9 | + |
| 10 | + try { |
| 11 | + // Some code that can throw an exception |
| 12 | + } catch(const std::exception&) { |
| 13 | + } |
| 14 | + |
| 15 | +Having empty catch statements in a codebase can be a serious problem that |
| 16 | +developers should be aware of. Catch statements are used to handle exceptions |
| 17 | +that are thrown during program execution. When an exception is thrown, the |
| 18 | +program jumps to the nearest catch statement that matches the type of the |
| 19 | +exception. |
| 20 | + |
| 21 | +Empty catch statements, also known as "swallowing" exceptions, catch the |
| 22 | +exception but do nothing with it. This means that the exception is not handled |
| 23 | +properly, and the program continues to run as if nothing happened. This can |
| 24 | +lead to several issues, such as: |
| 25 | + |
| 26 | +* *Hidden Bugs*: If an exception is caught and ignored, it can lead to hidden |
| 27 | + bugs that are difficult to diagnose and fix. The root cause of the problem |
| 28 | + may not be apparent, and the program may continue to behave in unexpected |
| 29 | + ways. |
| 30 | + |
| 31 | +* *Security Issues*: Ignoring exceptions can lead to security issues, such as |
| 32 | + buffer overflows or null pointer dereferences. Hackers can exploit these |
| 33 | + vulnerabilities to gain access to sensitive data or execute malicious code. |
| 34 | + |
| 35 | +* *Poor Code Quality*: Empty catch statements can indicate poor code quality |
| 36 | + and a lack of attention to detail. This can make the codebase difficult to |
| 37 | + maintain and update, leading to longer development cycles and increased |
| 38 | + costs. |
| 39 | + |
| 40 | +* *Unreliable Code*: Code that ignores exceptions is often unreliable and can |
| 41 | + lead to unpredictable behavior. This can cause frustration for users and |
| 42 | + erode trust in the software. |
| 43 | + |
| 44 | +To avoid these issues, developers should always handle exceptions properly. |
| 45 | +This means either fixing the underlying issue that caused the exception or |
| 46 | +propagating the exception up the call stack to a higher-level handler. |
| 47 | +If an exception is not important, it should still be logged or reported in |
| 48 | +some way so that it can be tracked and addressed later. |
| 49 | + |
| 50 | +If the exception is something that can be handled locally, then it should be |
| 51 | +handled within the catch block. This could involve logging the exception or |
| 52 | +taking other appropriate action to ensure that the exception is not ignored. |
| 53 | + |
| 54 | +Here is an example: |
| 55 | + |
| 56 | +.. code-block:: c++ |
| 57 | + |
| 58 | + try { |
| 59 | + // Some code that can throw an exception |
| 60 | + } catch (const std::exception& ex) { |
| 61 | + // Properly handle the exception, e.g.: |
| 62 | + std::cerr << "Exception caught: " << ex.what() << std::endl; |
| 63 | + } |
| 64 | + |
| 65 | +If the exception cannot be handled locally and needs to be propagated up the |
| 66 | +call stack, it should be re-thrown or new exception should be thrown. |
| 67 | + |
| 68 | +Here is an example: |
| 69 | + |
| 70 | +.. code-block:: c++ |
| 71 | + |
| 72 | + try { |
| 73 | + // Some code that can throw an exception |
| 74 | + } catch (const std::exception& ex) { |
| 75 | + // Re-throw the exception |
| 76 | + throw; |
| 77 | + } |
| 78 | + |
| 79 | +In some cases, catching the exception at this level may not be necessary, and |
| 80 | +it may be appropriate to let the exception propagate up the call stack. |
| 81 | +This can be done simply by not using ``try/catch`` block. |
| 82 | + |
| 83 | +Here is an example: |
| 84 | + |
| 85 | +.. code-block:: c++ |
| 86 | + |
| 87 | + void function() { |
| 88 | + // Some code that can throw an exception |
| 89 | + } |
| 90 | + |
| 91 | + void callerFunction() { |
| 92 | + try { |
| 93 | + function(); |
| 94 | + } catch (const std::exception& ex) { |
| 95 | + // Handling exception on higher level |
| 96 | + std::cerr << "Exception caught: " << ex.what() << std::endl; |
| 97 | + } |
| 98 | + } |
| 99 | + |
| 100 | +Other potential solution to avoid empty catch statements is to modify the code |
| 101 | +to avoid throwing the exception in the first place. This can be achieved by |
| 102 | +using a different API, checking for error conditions beforehand, or handling |
| 103 | +errors in a different way that does not involve exceptions. By eliminating the |
| 104 | +need for try-catch blocks, the code becomes simpler and less error-prone. |
| 105 | + |
| 106 | +Here is an example: |
| 107 | + |
| 108 | +.. code-block:: c++ |
| 109 | + |
| 110 | + // Old code: |
| 111 | + try { |
| 112 | + mapContainer["Key"].callFunction(); |
| 113 | + } catch(const std::out_of_range&) { |
| 114 | + } |
| 115 | + |
| 116 | + // New code |
| 117 | + if (auto it = mapContainer.find("Key"); it != mapContainer.end()) { |
| 118 | + it->second.callFunction(); |
| 119 | + } |
| 120 | + |
| 121 | +In conclusion, empty catch statements are a bad practice that can lead to hidden |
| 122 | +bugs, security issues, poor code quality, and unreliable code. By handling |
| 123 | +exceptions properly, developers can ensure that their code is robust, secure, |
| 124 | +and maintainable. |
| 125 | + |
| 126 | +Options |
| 127 | +------- |
| 128 | + |
| 129 | +.. option:: IgnoreCatchWithKeywords |
| 130 | + |
| 131 | + This option can be used to ignore specific catch statements containing |
| 132 | + certain keywords. If a ``catch`` statement body contains (case-insensitive) |
| 133 | + any of the keywords listed in this semicolon-separated option, then the |
| 134 | + catch will be ignored, and no warning will be raised. |
| 135 | + Default value: `@TODO;@FIXME`. |
| 136 | + |
| 137 | +.. option:: AllowEmptyCatchForExceptions |
| 138 | + |
| 139 | + This option can be used to ignore empty catch statements for specific |
| 140 | + exception types. By default, the check will raise a warning if an empty |
| 141 | + catch statement is detected, regardless of the type of exception being |
| 142 | + caught. However, in certain situations, such as when a developer wants to |
| 143 | + intentionally ignore certain exceptions or handle them in a different way, |
| 144 | + it may be desirable to allow empty catch statements for specific exception |
| 145 | + types. |
| 146 | + To configure this option, a semicolon-separated list of exception type names |
| 147 | + should be provided. If an exception type name in the list is caught in an |
| 148 | + empty catch statement, no warning will be raised. |
| 149 | + Default value: empty string. |
0 commit comments