0

因此,在处理一个真正的巫毒错误一周后(已解决,但当然,通过#include在相关位置添加一个)我意识到一个人不应该总是信任调试器,如果某些事情没有意义,很好oldprintf()可能对你有用。据我所知,如果代码在发布模式下编译,调试器可能会“撒谎”。我最近了解到,如果一个类有一个#ifdef,类似

struct MyStruct
{
    char a;
#ifdef USE_ME
    double c;
#else
    int c;
#endif
};

并且USE_ME未在结构定义可见的标头中定义,而是在其他地方定义,调试器会感到困惑,因为它不知道 c 是什么类型并且会“撒谎”,即使我们处于调试模式。我的问题是:谁能给出调试器何时撒谎的其他情况?

4

3 回答 3

4

调试器通常不会说谎(除非它有问题)。它准确地告诉您程序中发生了什么。您的问题是程序中发生的事情与您认为程序中发生的事情不同 - 或者与您在源代码中编写的不同。

当编译器优化您的代码时(例如,当您构建发布版本时),它会以多种方式转换代码,这意味着操作将被重新排序或完全删除。

当您进行调试时,调试器会尽力将正在发生的事情与源代码中编写的内容相关联,但它不能完美地做到这一点,因为编译器可能选择了完全不同的方式来实现相同的目标。因此,您经常会看到在调试器中根本看不到变量(它们已被优化),或者它们具有意外的值,或者您会看到调试器似乎在不同的源代码行之间随机跳转。

所以调试器不会说谎。它只是告诉你一个与你预期不同的事实。它告诉您程序中实际发生的事情的真相——而不是源代码中所写内容的“真相”。

于 2012-06-10T13:13:34.850 回答
1

谎言的典型示例发生在内存损坏(堆栈或堆损坏)以及一般与内存相关的问题(例如悬空引用)。

这是调用未定义行为的结果之一,即使调试器的行为在这种情况下也是未定义的,因为调试器正在使用无效的编译代码工作。

调试器擅长帮助解决格式良好的程序中的逻辑问题,并且可以帮助发现格式错误的程序中的一些错误(例如 null 取消引用);但并非所有类型的格式错误的程序都可以被有效地调试。当然,在多线程程序(等等)中事情变得更加棘手,因为观察程序的事实改变了它的行为......

于 2012-06-10T13:22:15.003 回答
0

调试器可能存在两种情况:

  1. 您正在调试缺少/不正确的符号(包括您的符号和操作系统的符号)。
  2. 你的身材不好。也许一些陈旧的 .OBJ 被链接,而不是首先被重建。这有时会发生在大型项目/解决方案上,特别是如果您使用“老式”指定项目依赖项的方式而不是 VS2010 的官方方式。
于 2012-06-10T13:19:52.597 回答