在 Visual Studio 2017 中,我创建了一个调用 C++ 函数的 .natvis 调试器可视化规则。
在调试器中显示:
这个表达式有副作用,不会被计算。
除此之外,它还显示了一个蓝色的小箭头,可以单击该箭头以强制其求值,然后它实际上会调用该函数。 (我认为这可能是最近的一个功能,因为我似乎记得在 VS2013 中尝试过这个并且不记得它有绕过)
我的问题是:有没有什么方法可以永久绕过这个安全检查,让它总是立即评估我的功能,而不需要我点击箭头?
我看过一个非常相似的问题:"This expression causes side effects and will not be evaluated". How to suppress?其中接受的答案仅对 C# 有效(在 C# 表达式末尾添加 ,ac 会强制调试器自动重新评估它)
我想如果存在这样的事情,那将是以下机制之一:
- 始终禁用安全检查的注册表设置或其他全局设置。
- 一种注释代码或 .natvis 规则的方法,以便编译器以某种方式知道它是一个安全且纯无副作用的函数
要提供有关该应用程序的更多详细信息:我们在我们的代码中到处使用 uint32,它们是从字符串散列的,并且我们有一个仅在开发版本中加载的字符串数据库。解码函数在二叉搜索树中查找 u32 ID,返回在存储节点中找到的字符串。所以我知道它完全没有副作用,而且速度足够快,不会影响调试体验,只要每次 .natvis 规则这么说就调用函数。
最佳答案
经过进一步研究,我怀疑没有办法告诉 Visual Studio 您的函数没有副作用,即使对于像 int MyTestFunction() { return 56; }
这样微不足道的无副作用函数也是如此。它仍然会在监 window 口中给出“表达式有副作用,不会被计算”的消息。
虽然这不是一个非常令人满意的答案,但我确实找到了解决这个问题的方法,即使用笨拙、丑陋的方法重新实现我试图调用的函数(在我的例子中是通过表进行二进制搜索) .natvis 的 XML 语法 CustomListItems
标签。
尽管这个标签的名称暗示它与列表有关,但看起来这个标签对于任何需要某种算法来实现的可视化工具来说都是一种万能的。在下<CustomListItems>
你可以使用一堆不同的标签,这些标签可能足以实现几乎任何算法:
-
<Variable>
用于声明变量的标签, -
<Loop>
迭代标签, -
<Break Condition="myCondition">
用于检查是否终止循环, -
<Exec>
用于执行表达式的标签,改变在<Variable>
中声明的变量的值标签, -
<If Condition="myCondition">
用于分支 - 您可以包含任意数量的
<Item Name="name">value</Item>
标签,其中每一个都将在正在展开的变量下方的监 window 口中显示为一行。
据我所知,这些算法标签中的大部分只能在 CustomListItems
下使用(我只尝试使用一些 <Expand>
标签的常规 <Variable>
规则,但出现错误,表明它不受支持)
不得不重新实现一个已经在这种可怕的语法中工作的 C++ 函数并不是一件令人愉快的事(请记住陷阱,比如必须使用 >
和 <
代替 >
和 <
因为它是 XML)。
然而,通过以下几个技巧,它并没有想象中的那么糟糕
- 如果您在 visual studio 中编辑 .natvis 文件,保存该文件会触发调试器重新评估显示,而无需重新启动您的程序,因此迭代您的 .natvis 规则非常快。 (注意:当从外部编辑器编辑 .natvis 文件时,这在 VS2017 中似乎对我不起作用)
- 大量使用
<Item>
在你的规则中标记,你基本上可以做相当于“打印调试”的事情。在尝试使您的 .natvis 规则生效时,请使用<Item>
打印出中间值。如果算法无法正常工作,这将使追踪算法失败的位置变得更加容易。工作时删除这些额外的标签。
您可以找到 CustomListItems
的文档和示例在这里。
关于c++ - 有没有办法绕过 "This expression has side effects and will not be evaluated."?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47041809/