在 Visual Studio 2022 17.10 预览版 2 中,我们改善了一些小功能,例如:在调试版本中,变量窗口现已可以显示调用堆栈中任意帧的局部变量。
如需体验此功能,请直接安装最新预览版本,就可以知道是怎么一回事儿了。
问题:变量窗口中缺失的东西
你是否碰到过这样的问题?
我们正在调试一些代码,并在函数 foo 中命中了一个断点。我们需要在调用堆栈的上方检查一些局部变量的值,因此我们打开调用堆栈窗口并单击该帧。
在本例中,我们希望看到变量 y 的值,该值是计算我们正在检查的函数 foo 的参数的输入。很遗憾,它不会出现在本地变量窗口中,如下图所示:
>> 请移步至 www.topomel.com 以查看图片 <<
该变量无法显示的原因与范围界定以及调用堆栈的遍历方式有关。变量 y 的作用域仅限于该 if 语句;当您位于 if 块之外时,Y 将不再存在。
而且,调用堆栈的工作方式是,我们用来确定作用域的返回地址实际上是调用后的下一条指令,或者在本例中是 return 语句。
改善变量可见性
在 Visual Studio 2022 17.10 预览版 2 中,我们解决了此问题。
现在,在这个示例程序中,您将看到变量 y 的值,如下图所示:
>> 请移步至 www.topomel.com 以查看图片 <<
我们可以看到,断点位于同一位置,但现在当您单击上一帧时,您会看到“下一个语句”箭头仍指向调用,因此该作用域中的所有变量现在都可用。
我们是怎么做到的?好吧,我们可以采取很多方法,但我们采用的方法之一是更改调试构建的代码生成,以在每次结束词法范围的调用后包含nop指令(并且仅包含作为范围中最终指令的调用)。
>> 请移步至 www.topomel.com 以查看图片 <<
调用 foo 后的额外 nop 指令是使其工作的原因。它位于同一范围内,因此一切都按预期工作,而无需修改调试器或堆栈遍历算法。这样做的优点是还可以在较旧的调试器上工作。
需要注意的是,此方法确实会增加调试版本中生成的代码大小,因此如果出现问题,我们添加了一个开关来禁用此行为。
只需将
/d2EnsureCallScopeForDebugging- 添加到项目命令行下的“其他选项”中,即可获得之前不生成额外 nops 的行为:
>> 请移步至 www.topomel.com 以查看图片 <<
总结
我可以感受到,Visual Studio 开发团队确实在细节上下功夫了。
希望大家可以下载最新版本把玩把玩,但记得别耽误正事儿!
最后
Microsoft Visual C++团队的博客是我非常喜欢的博客之一,里面有很多关于Visual C++的知识和最新开发进展。大浪淘沙,如果你对Visual C++这门古老的技术还是那么感兴趣,则可以经常去他们那(或者我这)逛逛。
本文来自:《Improvements in Variable Visibility when Debugging》