{"id":32325,"date":"2023-06-26T16:19:51","date_gmt":"2023-06-26T16:19:51","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=32325"},"modified":"2023-06-26T16:19:51","modified_gmt":"2023-06-26T16:19:51","slug":"using-key-events-with-warning-c26800","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/using-key-events-with-warning-c26800\/","title":{"rendered":"Using Key Events with warning C26800"},"content":{"rendered":"<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/microsoft-cpp-code-analysis-warnings-with-key-events\/\">MSVC&#8217;s Code Analysis Key Events<\/a> are a useful tool for quickly getting to the root-cause of your static analysis warnings. This blog post highlights how Key Events may be used with warning <a href=\"https:\/\/learn.microsoft.com\/cpp\/code-quality\/c26800?view=msvc-170\"><code>C26800<\/code><\/a> <code>Use of a moved from object<\/code> to quickly narrow down the problematic code.<\/p>\n<h2>C26800 warning recap<\/h2>\n<p>Warning C26800 catches code that attempts to use an object that is in a moved-from state:<\/p>\n<pre><code class=\"language-cpp\">#include &lt;iostream&gt;\r\nint main()\r\n{\r\n    std::string string_owner = \"this string will be moved!\";\r\n    std::string new_string_owner = std::move(string_owner);\r\n    std::cout &lt;&lt; string_owner &lt;&lt; std::endl; \/\/ Warning C26800 Use of a moved from object: ''string_owner'' (lifetime.1).\r\n}<\/code><\/pre>\n<p>Instead of <code>this string will be moved!<\/code>, the print statement in the above example will produce an empty output line when run.<\/p>\n<p>The move from <code>string_owner<\/code> into <code>new_string_owner<\/code> happens on the line <em>immediately<\/em> preceding its use in the print statement, so it&#8217;s instantly clear why the output is incorrect. But this is a trivial example. Real world code is rarely this straightforward.<\/p>\n<h2>A more complex example, sans Key Events<\/h2>\n<p>Consider a more convoluted example. The following code defines a function that is not only significantly longer than in the first code snippet, but is also littered with all sorts of intervening business logic (represented by <code>\/\/ ...<\/code>).<\/p>\n<pre><code class=\"language-cpp\">#include &lt;string&gt;\r\nvoid take_ownership(std::string&amp;&amp;) { \/* ... *\/ }\r\nvoid use_string(std::string) { \/* ... *\/ }\r\nvoid my_buggy_function(bool some_condition, bool some_other_condition)\r\n{\r\n    std::string my_string{ \"this is a string!\" };\r\n    bool my_flag{ false };\r\n\r\n    \/\/ ...\r\n\r\n    if (some_condition)\r\n    {\r\n        take_ownership(std::move(my_string)); \/\/ (a)\r\n    }\r\n\r\n    \/\/ ...\r\n\r\n    if (some_other_condition) \/\/ (b)\r\n    {\r\n        my_flag = true;\r\n\r\n        \/\/ ...\r\n\r\n        my_string = \"the string is reset\"; \/\/ (c)\r\n\r\n        \/\/ ...\r\n    }\r\n\r\n    \/\/ ...\r\n\r\n    if (my_flag &amp;&amp; !some_other_condition) \/\/ (d)\r\n    {\r\n        take_ownership(std::move(my_string)); \/\/ (e)\r\n    }\r\n\r\n    \/\/ ...\r\n\r\n    use_string(my_string); \/\/ Use of a moved from object: ''my_string'' (lifetime.1). (f)\r\n}<\/code><\/pre>\n<p>As in the simple example, a developer tasked with solving this bug will be looking to answer the question: where is <code>my_string<\/code> moved? A natural approach would likely be to start on line <code>(f)<\/code>, and to scan backwards through the code. This process would look something like:<\/p>\n<ul>\n<li>Starting at the warning location and looking a few lines up, the <code>take_ownership(std::move(my_string));<\/code> on line <code>(e)<\/code> immediately offers itself up as the culprit. To realize that this is a red-herring requires evaluating the condition on line <code>(d)<\/code>, which requires tracing even higher up into the function&#8217;s depths, delving further into the confusing business logic.<\/li>\n<li>Eventually, once satisfied that the move on line <code>(e)<\/code> is actually unreachable (oops!), the developer recommences the upwards traversal, eventually landing on the <code>move<\/code> on line <code>(a)<\/code>. But not before noticing the write to <code>my_string<\/code> on line <code>(c)<\/code>.<\/li>\n<li>The developer must now solve the puzzle of why this re-assignment (on line <code>(c)<\/code>) is not preventing the warning all the way down on line <code>(f)<\/code>.<\/li>\n<li>After spending far too long running back and forth through the code, the developer finally convinces themselves that it might be possible for the condition on line <code>(b)<\/code> to be false, thus skipping the reset on line <code>(c)<\/code>. The mystery is finally solved.<\/li>\n<\/ul>\n<p>There must be an easier way. Enter Key Events.<\/p>\n<h2>Solution made simple with Key Events<\/h2>\n<p>As of Visual Studio 17.5 Preview 1, Key Events have been enabled for the warning C26800. Using the <a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/microsoft-cpp-code-analysis-warnings-with-key-events\/#presentation-of-key-events-through-sarif-viewer-extension\">Microsoft SARIF Viewer extension<\/a>, this check can now precisely explain its assumptions and reasoning to the curious developer, all via inline annotations in the buggy code!<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2023\/06\/sarif_extension.png\" alt=\"Key Events with warning C26800\" \/><\/p>\n<p>These Key Events offer precisely the troublesome code path that the developer was searching for and (eventually) arrived at via manual inspection of the function&#8217;s code. Notably, we see that the check:<\/p>\n<ul>\n<li>is concerned with the move on line <code>(a)<\/code>, helpfully noting that its guarding condition <code>some_condition<\/code> could be <code>true<\/code><\/li>\n<li>points out that there is nothing stopping the conditions on line <code>(b)<\/code> and <code>(d)<\/code> from being <code>false<\/code><\/li>\n<\/ul>\n<p>The buggy control flow leading to the usage of the moved-from <code>my_string<\/code> variable is therefore immediately made clear to the satisfied developer, and the investigation time is greatly reduced.<\/p>\n<h2>Summary<\/h2>\n<p>Prior to the addition of Key Events to MSVC&#8217;s warning C26800, complex code made it hard to debug and get to the root-cause of the warning. Now, with Key Events enabled by default for warning C26800, developers can much more easily identify and resolve instances of use-after-free warnings in their code. This feature was enabled in Visual Studio 17.5 Preview 1, so please <a href=\"https:\/\/visualstudio.microsoft.com\/vs\/features\/cplusplus\/\">download a recent version<\/a> and try it out. You can share your thoughts and comments with us through <a href=\"https:\/\/developercommunity.visualstudio.com\/cpp\">Developer Community<\/a>, Twitter (<a href=\"https:\/\/twitter.com\/visualc\">@VisualC<\/a>), or via email at <a href=\"mailto:visualcpp@microsoft.com\">visualcpp@microsoft.com<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s how you can use Key Events to fix warning C26800<\/p>\n","protected":false},"author":82454,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,216,256],"tags":[],"class_list":["post-32325","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus","category-documentation","category-experimental"],"acf":[],"blog_post_summary":"<p>Here&#8217;s how you can use Key Events to fix warning C26800<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/32325","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/82454"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=32325"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/32325\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=32325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=32325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=32325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}