0

在花了一点时间想知道为什么我的应用程序在附加调试器的情况下运行特定场景的速度非常缓慢后,我发现这是由于有一个条件断点(其条件从未被满足)。这似乎是合理的,因为 CPU 会发出断点信号,而 VS 需要在允许继续执行之前评估条件。这些转变必须是昂贵的。

我假设未执行的代码路径中的断点对运行时没有影响。

所以我的问题是双重的:

  1. 是否有任何资源可以量化与条件断点相关的成本,如果有,是否可以采取任何措施来降低其运行时评估成本?
  2. 是否有与“禁用”断点相关的任何成本?禁用是指 VS 在排水沟中用空心圆圈显示断点标记。

当然,如果我上面提到的任何事情都没有意义,那么请指出我正确的方向。

4

5 回答 5

5

很难量化条件断点的成本。条件断点中的表达式使用与您在监视或立即窗口中键入完全相同的语义进行评估。这种性质的表达式实际上并没有在客户端程序中执行,而是由特定于语言的表达式求值器处理。以有意义的方式描述这些类型的评估是不可能的。

但是我可以列出一些已知在调试窗口评估中速度较慢的东西

  • 函数调用:它们是您可以做的最慢的事情,因为函数调用需要重新启动被调试进程,以便 func eval 可以在进程中发生
  • 字符串比较:在后台这些返回到 func evals

至于禁用断点,不,它们不会影响应用程序的运行。

于 2009-10-19T15:55:32.687 回答
2

需要注意的一件事(我学得很辛苦)是确保在将变量与值进行比较时放置 == 而不是单个 =

断点编辑器不会警告您,但是在评估断点时,变量会被更改!我花了一些时间来调试我的代码!

另外,如果我真的需要条件断点来调试代码;我将条件添加到代码中,然后添加类似 string stop = "here"; 之类的内容。并在那里放置一个正常的断点 - 我发现代码运行得更快。

于 2010-06-09T14:16:52.043 回答
0

我还注意到条件断点很昂贵,并且得出的结论与您相同。我无法想象禁用断点会导致任何减速的任何原因,因为我希望它只是一个编辑器,是在需要时打开断点的快捷方式。

当我遇到像你这样的情况时,我会做一个断言宏。(你可以使用visual studio提供的assert宏,但我不喜欢)。让您的宏检查您想要的条件,然后在失败时调用DebugBreak 。在应用程序的发布或未经检查的构建中,断言评估为空,因此您的代码不会受到影响。

一个简单的断言宏可以如下所示:

#ifdef _DEBUG
#define assert(x)\
do{\
  if(!(x)){DebugBreak();}\
}while(0)
#else
#define assert(x)
#endif

并称之为:

assert(pValue != NULL && "A bad parameter was passed to the function");

您可以在 DebugBreak 之前在失败中添加更多代码(例如使用 #x 打印失败的条件,和/或使用 ____FILE____ 和 ____LINE____ 打印行/文件号,以便您可以双击消息)。您可以使用OutputDebugString将消息写入调试日志,甚至可以检查是否使用IsDebuggerPresent附加了调试器以进一步定制您的断言。我还喜欢使用 && 字符串格式来提供有关特定断言的更多信息。

使用 assert 时需要注意一些事项。首先,不要在宏中放置任何必须运行的代码,因为它会在非调试版本中被剥离。出于同样的原因,不要放入有副作用的代码。此外,您不希望在未附加调试器时调用 DebugBreak(),因为它本质上会引发异常,如果未捕获该异常,将终止应用程序。

于 2009-10-19T16:13:55.943 回答
0

我在某处读到这些断点有硬件支持,因此使用少于 x 个特定类型的条件断点基本上是免费的,但除此之外,它需要使用更多的软件。(OTOH,那是针对本机应用程序的,不确定这些新奇的 JIT 东西。)

禁用的断点应该会产生影响,它们只是在 IDE 中占用一些内存和 GUI 资源。

于 2009-10-19T15:54:16.327 回答
0
  1. 尝试在代码中放置断点来测试性能。例如

    Stopwatch st = new Stopwatch();
    st.Start();
    if(my condition)
    {
      st.Stop();
      Debugger.Break();
    }
    

    不,不完全相同,但足够接近。

  2. 否 - 正在执行的程序中不存在禁用的断点。为方便起见,它只是存储在 VS 元数据中。

于 2009-10-19T15:55:03.750 回答