{"id":33766,"date":"2024-03-22T16:30:15","date_gmt":"2024-03-22T16:30:15","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=33766"},"modified":"2024-09-11T14:06:44","modified_gmt":"2024-09-11T14:06:44","slug":"improvements-in-variable-visibility-when-debugging","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/improvements-in-variable-visibility-when-debugging\/","title":{"rendered":"Improvements in Variable Visibility when Debugging"},"content":{"rendered":"<p>In Visual Studio 2022 17.10 Preview 2, we\u2019re including a small quality-of-life improvement that results in the Watch\/Locals window displaying local variables correctly for any arbitrary frames in the call stack in debug builds. To try it out, please install the recently released Preview. For more information, read on.\u00a0<\/p>\n<h4>The problem: missing variables in Watch Window<\/h4>\n<p>Have you ever been in this situation?\u00a0We\u2019re debugging some code, and have a breakpoint we hit in a function, <em>foo<\/em>. We need to inspect the values of some local variables a bit up the call stack, so we open up the call stack window and click to that frame. <\/p>\n<p>In this case, we want to see the value of the variable <em>y<\/em>, which is an input to calculate the argument to the function foo we\u2019re inspecting. Unfortunately, it\u2019s not available:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a.png\"><img decoding=\"async\" class=\"alignnone wp-image-33769 size-full\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a.png\" alt=\"variable y is not available\" width=\"975\" height=\"727\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a.png 975w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-300x224.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-768x573.png 768w\" sizes=\"(max-width: 975px) 100vw, 975px\" \/><\/a><\/p>\n<p>The reason it isn\u2019t available has to do with scoping, and how call stacks are walked. The variable <em>y<\/em> is scoped to just that one if statement; when you\u2019re outside the if block, <em>y<\/em> no longer exists. And, the way call stacks work, the return address we use to determine the scope is actually the next instruction after the call, or in this case, the <em>return<\/em> statement.<\/p>\n<h4>Improvements to variable visibility<\/h4>\n<p>In Visual Studio 2022 17.10 Preview 2, we\u2019ve addressed this \ud83d\ude4f <a href=\"https:\/\/developercommunity.visualstudio.com\/t\/VS-Debugger-CC-watch-doesnt-have-acc\/10445086\">Community Suggestion<\/a>. Now, in this toy example, you will see the value of the variable <em>y<\/em>:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-1.png\"><img decoding=\"async\" class=\"alignnone wp-image-33772 size-full\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-1.png\" alt=\"variable y is available\" width=\"975\" height=\"727\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-1.png 975w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-1-300x224.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-1-768x573.png 768w\" sizes=\"(max-width: 975px) 100vw, 975px\" \/><\/a><\/p>\n<p>The breakpoint is in the same location, but now when you click to the previous frame, you\u2019ll see the \u201cnext statement\u201d arrow still points to the call, so all the variables in that scope are now available.<\/p>\n<p>How did we do this? Well, there are a ton of approaches we could have taken, but the one we went with was to change the code generation of debug builds to include <em>nop<\/em> instructions after every call which ends a lexical scope (and only calls which are the final instruction in a scope).<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-2.png\"><img decoding=\"async\" class=\"alignnone wp-image-33773 size-full\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-2.png\" alt=\"nop inserted after call\" width=\"974\" height=\"580\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-2.png 974w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-2-300x179.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-2-768x457.png 768w\" sizes=\"(max-width: 974px) 100vw, 974px\" \/><\/a><\/p>\n<p>The extra <em>nop<\/em> instruction after the call to <em>foo<\/em> is what makes this work. It\u2019s located in the same scope, so everything works as expected without having to modify the debugger or the stack walking algorithm. This has the advantage of also working on older debuggers.<\/p>\n<p>This approach does increase the code size generated in Debug builds, so should something go wrong, we\u2019ve added a switch to disable this behavior. Just add <strong>\/d2EnsureCallScopeForDebugging-<\/strong> to the \u201cAdditional Options\u201d under the Command Line for your project, and you\u2019ll get the previous behavior of not generating extra <em>nops<\/em>:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-3.png\"><img decoding=\"async\" class=\"alignnone wp-image-33774 size-full\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-3.png\" alt=\"command line option added to disable this feature\" width=\"975\" height=\"685\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-3.png 975w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-3-300x211.png 300w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2024\/03\/a-3-768x540.png 768w\" sizes=\"(max-width: 975px) 100vw, 975px\" \/><\/a><\/p>\n<p>This switch may be removed in the future.<\/p>\n<h4>Send us your feedback<\/h4>\n<p>That\u2019s the feature, let us know if you find it helpful or find any issues. Please install Visual Studio 2022 17.10 Preview 2 and give it a try! We are very much interested in your feedback to continue to improve this experience. The comments below are open.<\/p>\n<p>We appreciate the time you took to report issues and sharing suggestions like this one. We hope you will continue to give us feedback when using Visual Studio about what you like and what we can improve.\u00a0Your feedback is critical to help us make Visual Studio the best tool it can be. Please share your feedback via <a href=\"https:\/\/developercommunity.visualstudio.com\/cpp\">Visual Studio Developer Community<\/a>. You can also reach us on X (<a href=\"https:\/\/twitter.com\/visualc\">@VisualC<\/a>), or via email at visualcpp@microsoft.com.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Visual Studio 2022 17.10 Preview 2, we\u2019re including a small quality-of-life improvement that results in the Watch\/Locals window displaying local variables correctly for any arbitrary frames in the call stack in debug builds. To try it out, please install the recently released Preview. For more information, read on.\u00a0 The problem: missing variables in Watch [&hellip;]<\/p>\n","protected":false},"author":310,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3946,1],"tags":[],"class_list":["post-33766","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-backend","category-cplusplus"],"acf":[],"blog_post_summary":"<p>In Visual Studio 2022 17.10 Preview 2, we\u2019re including a small quality-of-life improvement that results in the Watch\/Locals window displaying local variables correctly for any arbitrary frames in the call stack in debug builds. To try it out, please install the recently released Preview. For more information, read on.\u00a0 The problem: missing variables in Watch [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/33766","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\/310"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=33766"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/33766\/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=33766"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=33766"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=33766"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}