【问题标题】:How can I set a breakpoint on an empty statement in C++?如何在 C++ 中的空语句上设置断点?
【发布时间】:2012-02-20 09:14:05
【问题描述】:

具体来说,我想写一个宏

1) 允许我设置断点
2) 什么都不做
3) 不会导致编译器警告

#define NO_OP   ((void)0)

void main()
{
    bool b = true;
    if (b)
        NO_OP;  // I try to set a breakpoint here, but

}               // it jumps to here (in Visual Studio 2010)

我也试过

#define NO_OP   (assert(1))             // doesn't work
#define NO_OP   (sizeof(int))           // doesn't work
#define NO_OP   __asm{}                 // doesn't work
#define NO_OP   do {(void)0;} while(0)  // warning: conditional is constant

到目前为止,唯一有效的是令人畏惧

#define NO_OP   { int x = 0; x = x; }

必须有更好的方法。

编辑
感谢 Blorgbeard,__asm{ nop } 确实有效。但我刚刚意识到任何带大括号的东西都不完美(有问题?),因为它后面会留下一个无用的分号。 (后来)我不知道关于汇编器的深蹲,但我尝试移除大括号,瞧!答案是:__asm nop 谢谢!

为了好奇
这是一个稍微不那么荒谬的例子:

string token = GetNextToken();
if (!Ignore(token))
{
    // process token
    DoThis(token);
    DoThat(token);
}

这段代码是完整的——只要程序正常运行,我就不需要知道关于被忽略标记的任何事情。但是在任何给定时间(并且不更改代码)我想确保我不会拒绝好的令牌

string token = GetNextToken();
if (Ignore(token))
{
    NO_OP; // when desired, set breakpoint here to monitor ignored tokens
}
else
{
    // process token
    DoThis(token);
    DoThat(token);
}

【问题讨论】:

  • 调试器只能在可以执行某些代码的内存地址上设置断点。由于你没有正在执行的东西,它不能在那里设置断点。也许使用 asm volatile noop 操作码对你有用,但是再一次告诉我们你真正想要解决的问题可能会更好,因为这通常看起来是一种尴尬的方法
  • @PlasmaHH:这就是问题所在,我想要这样一个宏,为了简洁,我只是用一个荒谬的例子。
  • 为什么{int x = 0;} 值得畏惧?我的意思是,你只有在 _DEBUG 开启时才把它放在你的代码中,对吧?
  • @dog44wgm:“我想要这样一个宏”并不是真正要解决的问题。您希望宏解决某个问题,而谈论 那个 问题以提供真正的解决方案可能更有意义。
  • @Blorgbeard:那(没有大括号)正是我想要的,你能把它放在答案中以便我接受吗?

标签: c++ visual-studio-2010 debugging


【解决方案1】:

实际的无操作指令:

__asm nop

【讨论】:

  • 这是用于汇编的 MSVC 语法吗?在 GCC 中,它看起来必须是 __asm("nop")
【解决方案2】:

也许你可以这样做:

#define BREAKPOINT __asm { int 3; }

这将调用中断3,即断点中断。这将在您的代码中设置一个断点,该断点被编译作为代码的一部分。

现在,如果您只想要一些可以设置断点的操作,除了允许您在该行上中断之外,它基本上什么都不做。我认为你必须编译你的代码而不优化一件事,因为你实现的 NO_OP 很可能会被优化编译器从代码中优化出来,并打开优化开关。

另一点是,这似乎是一件很奇怪的事情。据我所知,通常会在想要查看的代码行上设置断点。看看变量状态是什么,一次只走一行,等等。我真的不明白在你的程序中基本上没有意义的代码行上设置断点将如何帮助你调试任何东西。

【讨论】:

  • 我认为“允许我设置断点”!=“无条件执行断点”。
  • @SteveJessop 如果他想设置断点,那么必须执行断点,不是吗?我看不出允许设置断点的意义,然后永远不会执行。如果 OP 在问这个问题,那么我没有答案。
  • 通常,调试器允许您指定哪些源代码行将在代码编译后执行断点,以及在代码开始运行后执行。无论调试器的用户做什么,您的建议都将断点放入可执行文件中。这些不是一回事。
【解决方案3】:

C++03:

inline void __dummy_function_for_NO_OP () {}
#define NO_OP __dummy_function_for_NO_OP ()

int main () {
    NO_OP;
}

C++11:

#define NO_OP [](){}()

int main () {
    NO_OP;
}

【讨论】:

    【解决方案4】:

    在 msvc x64 上有一个内在函数:

    __nop;
    

    【讨论】:

      【解决方案5】:

      __asm int 3 怎么样?另外,是否启用了优化?这可能是其他人失败的原因(实际上从未试图打破他们)。

      【讨论】:

        【解决方案6】:

        您可以定义一个全局unsigned int debug_counter,然后您的“no-op”宏可以是debug_counter++。很确定编译器不会删除它,但绝对可以肯定的是,在某处放置一些代码来打印计数器的值。

        【讨论】:

          【解决方案7】:

          myassert.h 中定义并包含在您的应用中的所有位置(强制包含在 Visual Studio 中?)。

          // Works cross-platform. No overhead in release builds
          #ifdef DEBUG
          
              // This function may need to be implemented in a cxx module if
              // your compiler optimizes this away in debug builds
              inline bool my_assert_func(const bool b)
              {
                  // can set true/false breakpoints as needed
                  if (b) {
                      return true;
                  }
                  else {
                      return false;
                  }
              }
          
              #define myassert(b) assert(my_assert_func(b))
          
          #else // RELEASE
          
              // In release builds this is a NOP
              #define myassert(b)    ((void)0)
          
          #endif
          
          #define DEBUG_BREAKPOINT myassert(true)
          

          现在你可以:

          string token = GetNextToken();
          if (Ignore(token)) 
              DEBUG_BREAKPOINT;
          }
          else {
              // process token
              DoThis(token);
              DoThat(token);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-06-18
            相关资源
            最近更新 更多