{"id":5480,"date":"2018-08-01T04:57:05","date_gmt":"2018-08-01T04:57:05","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-to-exception-handling\/"},"modified":"2023-06-26T11:47:07","modified_gmt":"2023-06-26T11:47:07","slug":"c-core-guidelines-rules-to-exception-handling","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-to-exception-handling\/","title":{"rendered":"C++ Core Guidelines: Rules about Exception Handling"},"content":{"rendered":"<p>Today&#8217;s post is about the right way to throw and catch exceptions. This means when you should throw and how you should catch an exception.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5479\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/08\/disappointment-3151237_1280.jpg\" alt=\"disappointment 3151237 1280\" width=\"700\" height=\"466\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/08\/disappointment-3151237_1280.jpg 1280w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/08\/disappointment-3151237_1280-300x200.jpg 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/08\/disappointment-3151237_1280-1024x682.jpg 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2018\/08\/disappointment-3151237_1280-768x512.jpg 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/p>\n<p>Here are the rules for today:<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-exception-types\">E.14: Use purpose-designed user-defined types as exceptions (not built-in types)<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-exception-ref\">E.15: Catch exceptions from a hierarchy by reference<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-never-fail\">E.16: Destructors, deallocation, and <code class=\"highlighter-rouge no-highlight\">swap<\/code> must never fail<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-not-always\">E.17: Don\u2019t try to catch every exception in every function<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-catch\">E.18: Minimize the use of explicit <code class=\"highlighter-rouge no-highlight\">try<\/code>\/<code class=\"highlighter-rouge no-highlight\">catch<\/code><\/a><\/li>\n<\/ul>\n<p>Let me jump directly into the first one.<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-exception-types\">E.14: Use purpose-designed user-defined types as exceptions (not built-in types)<\/a><\/h2>\n<p>You should not use standard exception types or even built-in types as an exception. Here are the two that don&#8217;t from the guidelines:<\/p>\n<h3>A built-in type<\/h3>\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">my_code<\/span>()     <span style=\"color: #0099ff; font-style: italic;\">\/\/ Don't<\/span>\r\n{\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">throw<\/span> <span style=\"color: #ff6600;\">7<\/span>;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ 7 means \"moon in the 4th quarter\"<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">your_code<\/span>()   <span style=\"color: #0099ff; font-style: italic;\">\/\/ Don't<\/span>\r\n{\r\n    try {\r\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n        my_code();\r\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">catch<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> i) {  <span style=\"color: #0099ff; font-style: italic;\">\/\/ i == 7 means \"input buffer too small\"<\/span>\r\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In this case, the exception is just an <span style=\"font-family: courier new, courier;\">int<\/span> without any semantics. What <span style=\"font-family: Courier New, Courier, monospace;\">7 <\/span>means stands in the comment, but should better be a self-describing type. The comment can be wrong. To be sure, you must look up the documentation to get an idea. You can not attach any meaningful information to an exception of kind <span style=\"font-family: courier new, courier;\">int<\/span>. If you have a <span style=\"font-family: Courier New, Courier, monospace;\">7<\/span>, I assume you use at least the numbers 1 to 6 for your exception handling. <span style=\"font-family: courier new, courier;\">1<\/span> meaning an unspecific error, and so on. This is too sophisticated, error-prone, and hard to read and maintain.<\/p>\n<h3>A standard exception<\/h3>\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">my_code<\/span>()   <span style=\"color: #0099ff; font-style: italic;\">\/\/ Don't<\/span>\r\n{\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">throw<\/span> runtime_error{<span style=\"color: #cc3300;\">\"moon in the 4th quarter\"<\/span>};\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">your_code<\/span>()   <span style=\"color: #0099ff; font-style: italic;\">\/\/ Don't<\/span>\r\n{\r\n    try {\r\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n        my_code();\r\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">catch<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> runtime_error<span style=\"color: #555555;\">&amp;<\/span>) {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ runtime_error means \"input buffer too small\"<\/span>\r\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Using a standard exception instead of a built-in type is better because you can attach additional information to an exception or build hierarchies of exceptions. This is better but not good.&nbsp; Why? The exception is too generic. It&#8217;s just a <span style=\"font-family: courier new, courier;\">runtime_error<\/span>. Image the function <span style=\"font-family: courier new, courier;\">my_code<\/span> is part of an input sub-system. If the caller of the function catches the exception by <span style=\"font-family: courier new, courier;\">std::runtime_error,<\/span> he has no idea if it was a generic error, such as &#8220;<span style=\"font-family: courier new, courier;\">input buffer too small<\/span>&#8221; or a sub-system-specific error, such as &#8220;<span style=\"font-family: courier new, courier;\">input device is not connected<\/span>&#8220;.<\/p>\n<p>To overcome these issues, derive your specific exception from <span style=\"font-family: courier new, courier;\">std::exception<\/span>. Here is a short example to give you an idea:<\/p>\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">InputSubSystemException<\/span><span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> std<span style=\"color: #555555;\">::<\/span>exception{\r\n    <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*<\/span> what() <span style=\"color: #006699; font-weight: bold;\">const<\/span> noexcept override {\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #cc3300;\">\"Provide more details to the exception\"<\/span>;\r\n    }\r\n};\r\n<\/pre>\n<\/div>\n<p>Now, the client of the input sub-system can specifically catch the exception via<span style=\"font-family: courier new, courier;\"> catch(const InputSubSystemException&amp; ex)<\/span>. You can also refine the exception hierarchy by deriving from the class <span style=\"font-family: courier new, courier;\">InputSubSystemException.<\/span><\/p>\n<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-exception-ref\">E.15: Catch exceptions from a hierarchy by reference<\/a><\/h2>\n<p>If you catch an exception from a hierarchy by value, you may become a victim of slicing.<\/p>\n<p>Imagine you derive from <span style=\"font-family: courier new, courier;\">InputSubSystemException<\/span> (rule E.14) a new exception class <span style=\"font-family: courier new, courier;\">USBInputException<\/span> and catch the exception by-value of type <span style=\"font-family: courier new, courier;\">InputSubSystemException.<\/span><span style=\"font-family: courier new, courier;\"> <\/span><span style=\"font-family: courier new, courier;\"><span style=\"font-family: Helvetica, Arial, sans-serif;\">Now, an exception of type<\/span><\/span><span style=\"font-family: courier new, courier;\"><span style=\"font-family: Helvetica, Arial, sans-serif;\"> <\/span><\/span><span style=\"font-family: courier new, courier;\">USBInputException<\/span> is thrown.<\/p>\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">subSystem<\/span>(){\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">throw<\/span> <span style=\"color: #00aa88; font-weight: bold;\">USBInputException<\/span><span style=\"color: #555555;\">();<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">clientCode<\/span>(){\r\n    try{\r\n        subSystem();\r\n    }\r\n    <span style=\"color: #006699; font-weight: bold;\">catch<\/span>(InputSubSystemException e) {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ slicing may happen<\/span>\r\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>By catching the <span style=\"font-family: courier new, courier;\">USBInputException<\/span> by-value to <span style=\"font-family: courier new, courier;\">InputSubSystemException, <\/span>slicing kicks in, and <span style=\"font-family: Courier New, Courier, monospace;\">e<\/span> has the simpler type&nbsp; <span style=\"font-family: courier new, courier;\">InputSubSystemException. <\/span>Please read the details of slicing in my previous post: <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-do-s-and-don-ts\">C++ Core Guidelines: Rules about Don&#8217;ts. <\/a><span style=\"font-family: Times New Roman, Times, serif;\"><br \/><\/span><\/p>\n<p>To say it explicitly:<\/p>\n<ol>\n<li>Catch your exception by const reference and only by reference if you want to modify the exception.<\/li>\n<li>If you rethrow an exception e in the exception handler, use throw and not throw e. In the second case, e would be copied.<span style=\"font-family: courier new, courier;\"><span style=\"font-family: Times New Roman, Times, serif;\"><br \/> <\/span><\/span><\/li>\n<\/ol>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-never-fail\">E.16: Destructors, deallocation, and <code class=\"highlighter-rouge no-highlight\">swap<\/code> must never fail<\/a><\/h2>\n<p>This rule&nbsp;is quite obvious. Destructors and deallocations should never throw because their any reliable way to handle an exception during the destruction of an object.<\/p>\n<p><span style=\"font-family: Courier New, Courier, monospace;\">swap <\/span>is often used as a basic building block for implementing copy and move semantics for a type. If an exception happens during <span style=\"font-family: Courier New, Courier, monospace;\">swap, <\/span>you are left with a non-initialized or not fully initialized object. Read more about the noexcept swap here: <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-comparison-swap-and-hash\">C++ Core Guidelines: Comparison, Swap, and Hash<\/a>.<span style=\"font-family: Times New Roman, Times, serif;\"><br \/><\/span><\/p>\n<p>The following two rules for the adequate usage of try and except are pretty similar.<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-not-always\">E.17: Don\u2019t try to catch every exception in every function<\/a> and<a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-catch\"> E.18: Minimize the use of explicit <code class=\"highlighter-rouge no-highlight\">try<\/code>\/<code class=\"highlighter-rouge no-highlight\">catch<\/code><\/a><\/h2>\n<p>From the control-flow perspective, <span style=\"font-family: Courier New, Courier, monospace;\">try\/catch<\/span> has much in common with the <span style=\"font-family: Courier New, Courier, monospace;\">goto <\/span>statement. This means if an exception is thrown, the control flow directly jumps to the exception handler which is maybe in a totally different function of even sub-system. In the end, you may get <a href=\"https:\/\/en.wikipedia.org\/wiki\/Spaghetti_code\">spaghetti code<\/a>; meaning code that has difficult to predict and maintain control flow.<\/p>\n<p>In the end, we are back to rule <a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Re-design\">E.1: Develop an error-handling strategy early in a design. <\/a><\/p>\n<p>Now, the question is: How should you structure your exception handling? I think you should ask yourself the question: Is it possible to handle the exception locally? If yes, do it. If not, let the exception propagate until you can sufficiently handle it. Often sub-system boundaries are the appropriate place to handle exceptions because you want to protect the client of the sub-system from arbitrary exceptions. At the boundary level, you have the regular and irregularly control flow interface. Regular communication is the functional aspect of the interface or what the system should do. Irregular communication stands for the non-functional aspects or how the system should perform. A big part of the non-functional aspects is the exception-handling and, therefore, the right place to handle the propagated exceptions.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Six rules for error handling are still left in the C++ core guidelines. They are the topic for the <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-when-you-can-t-throw-an-exception\">next post<\/a> before I go on with the rules of constants and immutability.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today&#8217;s post is about the right way to throw and catch exceptions. This means when you should throw and how you should catch an exception.<\/p>\n","protected":false},"author":21,"featured_media":5479,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[478,479],"class_list":["post-5480","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-error-handling","tag-exceptions"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5480","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5480"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5480\/revisions"}],"predecessor-version":[{"id":6817,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5480\/revisions\/6817"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5479"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5480"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5480"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5480"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}