19

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

您可以通过将变量或其他表达式放在花括号中来在消息中包含它的值...

允许哪些表达方式?

4

2 回答 2

18

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

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

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

用例

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

强制一个 if

非常简单:设置一个跟踪点来设置一个变量并强制 if 条件为真或假,具体取决于您需要测试的内容。所有这些都无需添加代码或离开调试会话。

断点“切换”

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

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

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

自动跳过代码

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

  1. 通过在“寄存器”窗口或带有“@eip,x”的“监视”窗口中中断一次并查看 EIP 的值来找到要跳到的行的地址。(请注意,寄存器窗口中的值是十六进制,但没有前导“0x”。)
  2. 使用步骤 1 中的地址,在要跳过的行上添加一个跟踪点,使用类似的表达式。{@eip = address}
  3. EIP 分配将在执行该行的任何内容之前发生。

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

于 2013-02-04T21:12:34.023 回答
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)}
于 2017-04-18T12:17:47.663 回答