本文介绍了跟踪点中允许使用哪些表达式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Visual Studio中创建跟踪点时(右键单击断点并选择"When Hit ..."),对话框中将显示以下文本,重点是我的:

When creating a tracepoint in Visual Studio (right-click the breakpoint and choose "When Hit..."), the dialog has this text, emphasis mine:

允许使用哪些表达式?

推荐答案

Microsoft的文档很少详细说明允许和不允许的内容.下面的大多数内容是在即时"窗口中通过反复试验发现的.请注意,此列表是针对C ++的,因为这就是我编写的代码.我相信C#实际上允许使用以下某些禁止的项目.

Microsoft's documentation is rather sparse on the exact details of what is and is not allowed. Most of the below was found by trial and error in the Immediate window. Note that this list is for C++, as that's what I code in. I believe in C#, some of the prohibited items below are actually allowed.

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

Most basic expressions can be evaluated, including casting, setting variables, and calling functions.

  • 仅支持C样式转换;没有static_cast,dynamic_cast,reinterpret_cast,const_cast
  • 无法声明新变量或创建对象
  • 不能使用重载运算符
  • 三元运算符不起作用
  • 不能使用逗号运算符,因为Visual Studio使用它来格式化结果的表达式;将多组花括号用于多个表达式
  • Only C-style casts supported; no static_cast, dynamic_cast, reinterpret_cast, const_cast
  • Can't declare new variables or create objects
  • Can't use overloaded operators
  • Ternary operator doesn't work
  • Can't use the comma operator because Visual Studio uses it to format the result of the expression; use multiple sets of braces for multiple expressions
  • 禁止通话:
    • Lambda(无法定义或调用)
    • 匿名命名空间中的功能
    • 按值获取对象的函数(因为无法创建对象)
    • Prohibited calls:
      • Lambdas (can't define or call them)
      • Functions in an anonymous namespace
      • Functions that take objects by value (because you can't create objects)
      • 常规和虚拟成员功能
      • 使用对基本类型或类类型的引用或指针的函数
      • 传递范围内变量
      • 使用&"将指针传递给作用域内变量
      • 传递文字"true","false",数字
      • 传递字符串文字,只要您不违反无法创建对象"规则
      • 使用多组花括号调用一个跟踪点的多个函数
      • 禁止:
        • 对象
        • 字符串文字
        • Prohibited:
          • Objects
          • String literals
          • 具有基本类型的变量,其值来自文字或其他变量
          • 强制转换后的内存地址:{ *(bool*)(0x1234) = true }
          • 寄存器:{ @eip = 0x1234 }
          • Variables with fundamental types, value either from literals or other variables
          • Memory addresses, after casting: { *(bool*)(0x1234) = true }
          • Registers: { @eip = 0x1234 }

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

          Calling functions from tracepoints can be quite powerful. You can get around most of the restrictions listed above with a carefully set up function and the right call. Here are some more specific ideas.

          非常简单:根据需要测试的内容,设置一个跟踪点以设置变量并强制将if条件设置为true或false.全部都无需添加代码或离开调试会话.

          Pretty straightforward: set up a tracepoint to set a variable and force an if-condition to true or false, depending on what you need to test. All without adding code or leaving the debug session.

          我已经看过几次这个问题:我需要闯入一个击中很多的位置.我想简单地从另一个断点启用该断点,因此我只在乎从某个代码路径中断.我该怎么办?"根据以上知识,这很容易,尽管您确实需要一个辅助变量.

          I've seen the question a few times, "I need to break in a spot that gets hit a lot. I'd like to simply enable that breakpoint from another breakpoint, so the one I care about only gets breaks from a certain code path. How can I do that?" With our knowledge above, it's easy, although you do need a helper variable.

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

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

          The nice thing is that you can move the tracepoints around without leaving the debugging session. Use the Immediate window or the Watch window to reset your global flag, if you need to make another run at it. When you're done, all you need to clean up is that global boolean. No other code to remove.

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

          The EIP register (at least on x86) is the instruction pointer. If you assign to it, you can change your program flow.

          1. 通过一次中断并通过"@ eip,x"在注册"窗口或监视"窗口中查看EIP的值来查找要跳至的行的地址. . (请注意,寄存器"窗口中的值为十六进制,但没有前导"0x".)
          2. 使用步骤1中的地址,在要跳过的行上添加一个跟踪点,并使用{@eip = address}这样的表达式.
          3. EIP分配将在执行任何 行之前发生.
          1. Find the address of the line you want to skip to by breaking on it once and looking at the value of EIP, either in the Registers window or the Watch window with "@eip,x". (Note that the value in the Registers window is hex, but without the leading "0x".)
          2. Add a tracepoint on the line you want to skip from, with an expression like {@eip = address}, using the address from step 1.
          3. EIP assignment will happen before anything on the line is executed.

          尽管这很方便,但是要小心,因为跳过这样的代码会导致奇怪的行为.

          Although this can be handy, be careful because skipping code like this can cause weird behavior.

          这篇关于跟踪点中允许使用哪些表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-30 21:53