【问题标题】:Triggering a breakpoint in a function that is not called在未调用的函数中触发断点
【发布时间】:2015-08-18 17:12:44
【问题描述】:

这是一个奇怪的问题。我在一个类上有一个函数,其中有一个断点,即使函数的其余部分没有运行,它也会被命中。重现此代码所需的代码量可能无法在此处发布,但这就是我所看到的:

MyClass.h:

enum OptionsEnum { OPTION_1, OPTION_2 };

struct OptionsStruct
{
    OptionsEnum options;
    int value;
};

class MyClass
{
private:
    Initialize(...);
    Process(const OptionsStruct&);

    OptionsStruct m_Options { };
}

MyClass.cpp:

#include "MyClass.h"

void MyClass::Initialize(...)
{
    ...do some stuff with local variables... //<--Breakpoint here not triggered
    ...do some more stuff...

    Process(m_Options); //<--Breakpoint here is triggered!  How?!

    ...do yet more stuff... //<--Breakpoint here not triggered
}

void MyClass::Process(const OptionsStruct& options)
{
    ...do some other stuff... //<--Breakpoint here not triggered
}

我看到很多帖子都有相反的问题,他们期望被命中的断点被优化出来,因此从未被触发,但我想不出相反的可能:优化导致在一个从未调用过的函数中间设置断点。

单步执行代码表明它从未真正进入Initialize() 函数,但是当使用断点运行时,它会触发它。可以肯定的是,我什至关闭了优化并让它运行,它仍然会到达那个断点。只有那个断点。我在函数的每一行代码上都放了一个断点,只有那个会命中。 Process() 中的断点也不会触发,即使它是由触发的那一行调用的。

模式似乎是只有其中包含成员变量的行才会被命中。当他们这样做时,如果您将鼠标悬停在 m_Options 上,则结构中的所有字段都是垃圾(未初始化)值。

调用堆栈没有帮助 - 它只指向[External Code] 和下面的[Frames below may be incorrect and/or missing...] 该函数是私有的,所以我不知道外部代码如何调用它。这是调试器中的错误吗?某种优化魔法?什么可能导致这样的事情发生?

【问题讨论】:

  • 确保你在调试模式下编译你的项目,没有优化。我可能只是猜测您将其编译为 RELEASE 或 DEBUG,但经过优化,编译器优化了一些使调试过程变得混乱的东西。
  • C++ 编译器 (clxx.exe) 在解释 OptionsStruct m_Options { }; 行时崩溃。如果我删除大括号,一切正常,没有断点被击中。很奇怪。
  • @AlexLop。我们实际上做了相反的事情——它被编译为 RELEASE 但没有优化。代码的其他部分取决于它是否处于发布版本中。我可以尝试回到 DEBUG,但每次切换模式时大约需要 20 分钟的编译时间(代码库非常庞大),所以我不经常这样做。
  • @AustinMullins - 你使用的是 C++11 吗?这在 C++0x 中不可用。它基本上只是用每个字段的默认值初始化结构。此外,我不希望其他人仅使用此代码就能看到相同的行为。我们的实际代码库非常大,不可能以任何有意义的方式在这里发布。
  • 是的,它是 C++11。我可以整天在_tmain 中做初始化列表和 lambda,当我试图在类定义中使用空的初始化列表时,我感到很困惑。

标签: c++ debugging c++11 visual-studio-2013 breakpoints


【解决方案1】:

内存损坏可能会导致问题。也许在你的代码中的某个地方你有一个损坏的指针,这可能是使用它的副作用。 它可以部分解释为什么你不能访问调用堆栈。 只是为了确定......断点是否与您运行的源代码完全相同?即使代码与编译版本不同,也可以调试。这会使断点变得无用。

【讨论】:

  • 是的,这绝对是相同的代码。我已经完成了完整的清理/重建,以确保我没有得到陈旧的代码。
  • 你有没有试过在程序的其他地方设置断点来定位触发问题的代码部分?如果在单步执行 wole 时问题不存在,则问题可能与并发相关。
  • 我确实在每个调用Initialize() 的调用点放置了一个断点,并且在断点触发之前它们都没有被命中。其中一些会在之后触发,但这是预期的行为。奇怪的是,函数中间的这一行在函数的任何其他部分或调用它的任何其他函数之前被击中......
  • 这就是为什么我会寻找可能出现在完全不同的代码部分中的内存损坏。我在考虑一个场景,您尝试在代码中的某处使用指针,但它指向的对象已被删除/不存在,现在它指向这条确切的行。执行可能会在 debud 模式下崩溃,但它有可能在发布时起作用。
  • 很可能你损坏了调用堆栈。常见的方法是在函数中声明为局部变量的 C 数组,然后写入超过其大小。然后,当声明该变量的函数试图返回时,你会得到一个疯狂的跳跃。你应该明白野跳所达到的函数和类可能与问题无关。
猜你喜欢
  • 2021-09-10
  • 2020-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-09
  • 2015-04-02
相关资源
最近更新 更多