【问题标题】:What expressions are allowed in tracepoints?跟踪点中允许哪些表达式?
【发布时间】:2013-01-19 16:23:20
【问题描述】:

在 Visual Studio 中创建跟踪点时(右键单击断点并选择“When Hit...”),对话框中有此文本,强调我的:

您可以在消息中包含变量或其他表达式的值,方法是将其放在花括号中...

允许哪些表达方式?

【问题讨论】:

    标签: visual-studio breakpoints trace


    【解决方案1】:

    Microsoft 的文档对于允许和不允许的具体细节相当少见。下面的大部分内容都是在“立即”窗口中通过反复试验发现的。请注意,此列表适用于 C++,因为这是我编写的代码。我相信在 C# 中,下面的一些违禁项目实际上是允许的。

    可以评估大多数基本表达式,包括转换、设置变量和调用函数。

    一般限制
    • 仅支持 C 样式转换;没有 static_cast、dynamic_cast、reinterpret_cast、const_cast
    • 无法声明新变量或创建对象
    • 不能使用重载的运算符
    • 三元运算符不起作用
    • 不能使用逗号运算符,因为 Visual Studio 将它用于format the result of the expression;对多个表达式使用多组大括号
    函数调用
    • 禁止调用:
      • Lambda(无法定义或调用它们)
      • 匿名命名空间中的函数
      • 按值获取对象的函数(因为您无法创建对象)
    • 允许的调用:
      • 常规和虚拟成员函数
      • 函数采用对基本类型或类类型的引用或指针
      • 传递范围内变量
      • 使用“&”将指针传递给范围内的变量
      • 传递文字“true”、“false”、数字
      • 传递字符串文字,只要您不违反“不能创建对象”规则
      • 通过使用多组大括号在一个跟踪点调用多个函数
    变量赋值
    • 禁止:
      • 对象
      • 字符串字面量
    • 允许:
      • 具有基本类型的变量,值来自文字或其他变量
      • 内存地址,转换后:{ *(bool*)(0x1234) = true }
      • 注册:{ @eip = 0x1234 }

    用例

    从跟踪点调用函数可能非常强大。通过精心设置的功能和正确的调用,您可以绕过上面列出的大部分限制。以下是一些更具体的想法。

    强制if

    非常简单:设置跟踪点以设置变量并强制 if 条件为真或假,具体取决于您需要测试的内容。无需添加代码或退出调试会话。

    断点“切换”

    我已经看过几次这个问题,“我需要在一个容易被很多击中的地方打断。我只想从另一个断点启用那个断点,所以那个我只关心某个代码路径的中断。我该怎么做?根据我们上面的知识,这很容易,尽管您确实需要一个辅助变量。

    1. 创建一个全局布尔值,设置为 false。
    2. 在最终目的地创建断点,条件是仅在全局标志为 true 时才中断。
    3. 在将全局标志分配为 true 的关键点设置跟踪点。

    好处是您可以在不离开调试会话的情况下移动跟踪点。如果您需要再次运行它,请使用立即窗口或监视窗口重置您的全局标志。完成后,您只需要清理该全局布尔值即可。无需删除其他代码。

    自动跳过代码

    EIP 寄存器(至少在 x86 上)是指令指针。如果你分配给它,你可以改变你的程序流程。

    1. 找到你想跳到的行的地址. (请注意,Registers 窗口中的值是十六进制,但没有前导“0x”。)
    2. 在您想要跳过的行上添加一个跟踪点,使用类似于{@eip = address} 的表达式,使用步骤 1 中的地址。
    3. EIP 分配将发生在行中的任何内容被执行之前。

    虽然这很方便,但要小心,因为跳过这样的代码会导致奇怪的行为。

    【讨论】:

    • 其中一个常规用法是在其中放置一个 Console.Writeline,它为您提供了一种在不实际更改代码的情况下插入日志语句的方法。再加上您可以使用 Debug->Breakpoints->Break at function... 选项在任何代码上定义断点(也可以在项目代码之外,甚至不管源代码可用性如何),这使得它非常强大。跨度>
    • 我找到了 MSDN 文章,其中讨论了表达式评估器允许和限制的内容:msdn.microsoft.com/en-us/library/y2t7ahxk.aspx
    • 上述评论中的 MSDN 链接是该页面的 最新 版本,显然微软决定从中删除一大堆信息。检查 Visual Studio 2013 的版本以查看以前的版本。我想可能某些/大部分信息不适用于更高版本的 Visual Studio,因此可能需要开发人员进行更多的试验和错误来进行调试。 msdn.microsoft.com/en-us/library/y2t7ahxk(v=vs.120).aspx
    【解决方案2】:

    正如 Kurt Hutchinson 所说,在跟踪点中不允许进行字符串分配。您可以通过创建一个分配字符串变量的方法并调用它来解决这个问题。

    public static class Helper
    {
        public static void AssignTo(this string value, out string variable)
        {
            variable = value;
        }
    }
    

    然后在您的跟踪点消息中:

    {"new string value".AssignTo(out stringVariable)}
    

    【讨论】:

    • 如果我们可以在 Conditions 表达式中指定断点会更好:在输出窗口中不打印空消息并使用 bool 返回值控制“继续执行” .不幸的是,这不起作用。当从断点条件调用它时,几乎就像在编译期间删除了部分方法体一样。很奇怪。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 2021-05-27
    • 1970-01-01
    • 2018-02-07
    • 2016-04-19
    相关资源
    最近更新 更多