{"id":22195,"date":"2019-01-24T09:33:37","date_gmt":"2019-01-24T17:33:37","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/?p=22195"},"modified":"2019-04-09T22:26:59","modified_gmt":"2019-04-09T22:26:59","slug":"lifetime-profile-update-in-visual-studio-2019-preview-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/lifetime-profile-update-in-visual-studio-2019-preview-2\/","title":{"rendered":"Lifetime Profile Update in Visual Studio 2019 Preview 2"},"content":{"rendered":"<p><span>The C++ Core Guidelines&#8217; Lifetime Profile, which is part of the <a href=\"https:\/\/github.com\/isocpp\/CppCoreGuidelines\">C++ Core Guidelines<\/a>, aims to detect lifetime problems, like dangling pointers and references, in C++ code. It uses the type information already present in the source along with some simple contracts between functions to detect defects at compile time with minimal annotation.<\/span><\/p>\n<p><span>These are the basic contracts that the profile expects code to follow:<\/span><\/p>\n<ol>\n<li><span>Don&#8217;t use a potentially dangling pointer.<\/span><\/li>\n<li><span>Don&#8217;t pass a potentially dangling pointer to another function.<\/span><\/li>\n<li><span>Don&#8217;t return a potentially dangling pointer from any function.<\/span><\/li>\n<\/ol>\n<p><span>For more information on the history and goals of the profile, check out <a href=\"https:\/\/herbsutter.com\/2018\/09\/20\/lifetime-profile-v1-0-posted\/\">Herb Sutter&#8217;s blog post about version 1.0<\/a>.<\/span><\/p>\n<h2>What&#8217;s New in Visual Studio 2019 Preview 2<\/h2>\n<p><span>In Preview 2, we&#8217;ve shipped a preview release of the Lifetime Profile Checker which implements the <a href=\"https:\/\/github.com\/isocpp\/CppCoreGuidelines\/blob\/master\/docs\/Lifetime.pdf\">published version of the Lifetime Profile<\/a>. This checker is part of the <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/code-quality\/using-the-cpp-core-guidelines-checkers?view=vs-2017\">C++ Core Checkers<\/a> in Visual Studio.<\/span><\/p>\n<ul>\n<li><span>Support for iterators, string_views, and spans.<\/span><\/li>\n<li><span>Better detection of custom Owner and Pointer types which allows custom types that behave like Containers, Owning-Pointers, or Non-Owning Pointers to participate in the analysis.<\/span><\/li>\n<li><span>Type-aware default rules for function call pre and post conditions help reduce false-positives and improve accuracy.<\/span><\/li>\n<li><span>Better support for aggregate types.<\/span><\/li>\n<li><span>General correctness and performance improvements.<\/span><\/li>\n<li><span>Some simple nullptr analysis.<\/span><\/li>\n<\/ul>\n<h2>Enabling the Lifetime Profile Checker Rules<\/h2>\n<p><span>The checker rules are not enabled by default. If you want to try out the new rules, you&#8217;ll have to update the code analysis ruleset selected for your project. You can either select the &#8220;C++ Core Check Lifetime Rules&#8221; &#8211; which enables only the Lifetime Profile rules &#8211; or you can modify your existing ruleset to enable warnings 26486 through 26489.<\/span><\/p>\n<p><figure id=\"attachment_22205\" aria-labelledby=\"figcaption_attachment_22205\" class=\"wp-caption alignnone\" ><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2019\/01\/lifetime-blog_image11.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2019\/01\/lifetime-blog_image11.png\" alt=\"Screenshot of the Code Analysis properties page that shows the C++ Core Check Lifetime Rules ruleset selected.\" class=\"size-full wp-image-22205\" width=\"1253\" height=\"898\" \/><\/a><figcaption id=\"figcaption_attachment_22205\" class=\"wp-caption-text\">Screenshot of the Code Analysis properties page that shows the C++ Core Check Lifetime Rules ruleset selected.<\/figcaption><\/figure><\/p>\n<p><span>Warnings will appear in the Error List when code analysis is run (Analyze &gt; Run Code Analysis), or if you have Background Code Analysis enabled, lifetime errors will show up in the editor with green squiggles.<\/span><\/p>\n<p><figure id=\"attachment_22215\" aria-labelledby=\"figcaption_attachment_22215\" class=\"wp-caption alignnone\" ><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2019\/01\/lifetime-blog_image21.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2019\/01\/lifetime-blog_image21.png\" alt=\"Screenshot showing a Lifetime Profile Checker warning with a green squiggle in source code.\" class=\"size-full wp-image-22215\" width=\"982\" height=\"134\" \/><\/a><figcaption id=\"figcaption_attachment_22215\" class=\"wp-caption-text\">Screenshot showing a Lifetime Profile Checker warning with a green squiggle in source code.<\/figcaption><\/figure><\/p>\n<h2>Examples<\/h2>\n<h3>Dangling Pointer<\/h3>\n<p><span>The simplest example \u2013 using a dangling pointer \u2013 is the best place to start. Here <code>px<\/code> points to <code>x<\/code> and then <code>x<\/code> leaves scope leaving <code>px<\/code> dangling. When <code>px<\/code> is used, a warning is issued.<\/span><\/p>\n<pre style=\"font-weight: 400\">void simple_test()\r\n{\r\n    int* px;\r\n    {\r\n        int x = 0;\r\n        px = &amp;x;\r\n    }\r\n    *px = 1; \/\/ error, dangling pointer to 'x'\r\n}<\/pre>\n<h3>Dangling Output Pointer<\/h3>\n<p><span>Returning dangling pointers is also not allowed. In this case, the parameter <code>ppx<\/code> is presumed to be an output parameter. In this case, it&#8217;s set to point to <code>x<\/code> which goes out of scope at the end of the function. This leaves <code>*ppx<\/code> dangling. <\/span><\/p>\n<pre style=\"font-weight: 400\">void out_parameter(int x, int** ppx)  \/\/ *ppx points to 'x' which is invalid\r\n{\r\n    *ppx = &amp;x;\r\n}\r\n<\/pre>\n<h3>Dangling String View<\/h3>\n<p><span>The last two examples were obvious, but temporary instances can introduce subtle bugs. Can you find the bug in the following code?<\/span><\/p>\n<pre style=\"font-weight: 400\">std::string get_string();\r\nvoid dangling_string_view()\r\n{\r\n    std::string_view sv = get_string();\r\n    auto c = sv.at(0);\r\n}<\/pre>\n<p><span>In this case, the string view <code>sv<\/code> is constructed with the temporary string instance returned from <code>get_string()<\/code>. The temporary string is then destroyed which leaves the string view referencing an invalid object.<\/span><\/p>\n<h3>Dangling Iterator<\/h3>\n<p><span>Another hard to spot lifetime issue happens when using an invalidated iterator into a container. In the case below, the call to <code>push_back<\/code> may cause the vector to reallocate its underlying storage which invalidates the iterator <code>it<\/code>. <\/span><\/p>\n<pre style=\"font-weight: 400\">void dangling_iterator()\r\n{\r\n    std::vector&lt;int&gt; v = { 1, 2, 3 };\r\n    auto it = v.begin();\r\n    *it = 0; \/\/ ok, iterator is valid\r\n    v.push_back(4);\r\n    *it = 0; \/\/ error, using an invalid iterator\r\n}<\/pre>\n<p><span>One thing to note about this example is that there is no special handling for \u2018std::vector::push_back\u2019. This behavior falls out of the default profile rules.<\/span> <span>One rule classifies containers as an &#8216;Owner&#8217;. Then, when a non-const method is called on the Owner, its owned memory is assumed invalidated and iterators that point at the owned memory are also considered invalid.<\/span><\/p>\n<h3>Modified Owner<\/h3>\n<p><span>The profile is prescriptive in its guidance. It expects your that code uses the type system idiomatically when defining function parameters. In this next example, <code>std::unique_ptr<\/code>, an &#8216;Owner&#8217; type, is passed to another function by non-const reference. According to the rules of the profile, Owners that are passed by non-const reference are assumed to be modified by the callee.<\/span><\/p>\n<pre style=\"font-weight: 400\">void use_unique_ptr(std::unique_ptr&lt;int&gt;&amp; upRef);\r\nvoid assumes_modification()\r\n{\r\n    auto unique = std::make_unique&lt;int&gt;(0); \/\/ Line A\r\n    auto ptr = unique.get();\r\n    *ptr = 10; \/\/ ok, ptr is valid\r\n    use_unique_ptr(unique);\r\n    *ptr = 10; \/\/ error, dangling pointer to the memory held by 'unique' at Line A\r\n}<\/pre>\n<p><span>In this example, we get a raw pointer, <code>ptr<\/code>, to the memory owned by <code>unique<\/code>. Then <code>unique<\/code> is passed to the function <code>use_unique_ptr<\/code> by non-const reference. Because this is a non-const use of <code>unique<\/code> where the function could do anything, the analysis assumes that <code>unique<\/code>&#8216; is invalidated somehow (e.g. unique_ptr::reset) which would cause <code>ptr<\/code> to dangle. <\/span><\/p>\n<h3>More Examples<\/h3>\n<p><span>There are many other cases that the analysis can detect. Try it out in Visual Studio on your own code and see what you find. Also check out <a href=\"https:\/\/herbsutter.com\/2018\/09\/20\/lifetime-profile-v1-0-posted\/\">Herb&#8217;s blog<\/a> for more examples and, if you&#8217;re curious, read through the Lifetime Profile paper. <\/span><\/p>\n<h2>Known Issues<\/h2>\n<p><span>The current implementation doesn&#8217;t fully support the analysis as described in the Lifetime Profile paper. Here are the broad categories that are not implemented in this release. <\/span><\/p>\n<ul>\n<li><b><span>Annotations<\/span><\/b><span> &#8211; The paper introduces annotations (i.e. <code>[[gsl::lifetime-const]]<\/code>) which are not supported. Practically this means that if the default analysis rules aren&#8217;t working for your code, there&#8217;s not much you can do other than <\/span><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/managing-warnings-in-the-c-core-guidelines-checker\/\"><span>suppressing<\/span><\/a><span> false positives. <\/span><\/li>\n<li><b><span>Exceptions<\/span><\/b><span> &#8211; Exception handling paths, including the contents of <code>catch<\/code> blocks, are not currently analyzed. <\/span><\/li>\n<li><b><span>Default Rules fo<\/span><\/b><b><span>r STL Types<\/span><\/b><span> &#8211; In lieu of a <code>lifetime-const<\/code> annotation, the paper recommends that for the rare STL container member functions where we want to override the defaults, we treat them as if they were annotated. For example, one overload of <code>std::vector::at<\/code> is not <code>const<\/code> because it can return a non-const reference &#8211; however we know that calling it is <code>lifetime-const<\/code> because it doesn&#8217;t invalidate the vector&#8217;s memory. We haven&#8217;t completed the work to do this implicit annotation of all the STL container types. <\/span><\/li>\n<li><b><span>Lambda Captures<\/span><\/b><span> &#8211; If a stack variable is captured by reference in a lambda, we don&#8217;t currently detect if the lambda leaves the scope of the captured variable. <\/span>\n<pre style=\"font-weight: 400\">auto lambda_test()\r\n{\r\n    int x;\r\n    auto captures_x = [&amp;x] { return x; };\r\n    return captures_x; \/\/ returns a dangling reference to 'x'\r\n}<\/pre>\n<\/li>\n<\/ul>\n<h2>Wrap Up<\/h2>\n<p><span>Try out the Lifetime Profile Checker in Visual Studio 2019 Preview 2. We hope that it will help identify lifetime problems in your projects. If you find false positives or false negatives, please report them so we can prioritize the scenarios that are important to you. If you have suggestions or problems with this check \u2014 or any Visual Studio feature \u2014 either <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/ide\/how-to-report-a-problem-with-visual-studio-2017\">Report a Problem<\/a> or post on <a href=\"https:\/\/developercommunity.visualstudio.com\/spaces\/62\/index.html\">Developer Community<\/a> and let us know. We&#8217;re also on Twitter at <a href=\"https:\/\/twitter.com\/visualc\"><span>@VisualC<\/span><\/a>.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The C++ Core Guidelines&#8217; Lifetime Profile, which is part of the C++ Core Guidelines, aims to detect lifetime problems, like dangling pointers and references, in C++ code. It uses the type information already present in the source along with some simple contracts between functions to detect defects at compile time with minimal annotation. These are [&hellip;]<\/p>\n","protected":false},"author":2869,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[230],"tags":[245,863,163],"class_list":["post-22195","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-new-feature","tag-cppcorecheck","tag-lifetime-profile","tag-static-analysis"],"acf":[],"blog_post_summary":"<p>The C++ Core Guidelines&#8217; Lifetime Profile, which is part of the C++ Core Guidelines, aims to detect lifetime problems, like dangling pointers and references, in C++ code. It uses the type information already present in the source along with some simple contracts between functions to detect defects at compile time with minimal annotation. These are [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/22195","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\/2869"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=22195"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/22195\/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=22195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=22195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=22195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}