程序状态和调试器不一致

Program state and debugger disagree

我在 Windows 7 上使用针对 2010 编译器构建的 VS2013(我们已经迁移了开发环境,但不是所有项目)。

我真的不知道如何描述这个问题,或者我会 google 它。我有一个指向字节缓冲区的指针,它是我们的有线协议(代码库早于 Google 及其协议缓冲区)。我们有 headers 表示一个 id 和一个类型;将指针转换为适当的类型,您就可以访问数据,如果数据的大小是动态的,如字符串字段,则为长度。 None 这应该是令人惊讶的,如果不是有点老派...

但我看到的是我有检查字段 ID 的代码 - 它永远不应该为零。但是条件命中,当我检查调试器中的元素时,缓冲区内容和指针位置都是正确的 - 字段是 non-zero.

所以我想问你的问题:

1) 我怎样才能更好地表达这个问题,这样我就可以 google 了?

2) 你以前见过这个吗?有什么想法吗?

这是一个远景,但是,我在项目未正确构建时看到过它。您可以尝试清理解决方案并重新构建它。

有一些问题(的组合)会像这样出现。

代码在生产设置中失败,但在调试时单步执行时却没有。在这种情况下,失败的真正罪魁祸首通常是一些其他不相关的代码滥用了指针(并且覆盖了它不应该覆盖的内存)。问题是,开发人员收到错误报告,然后使用调试器逐步执行代码。除了使用调试器之外,另一个区别是生产代码是用某种形式的 "full" 优化编译的,而代码是在没有优化的情况下重新编译的(并带有符号输出)供调试器使用。这改变了程序中数据(甚至代码)的内存布局。有问题的代码仍在骚扰它的指针,但内存中的其他内容正在被覆盖。这意味着调试时症状消失。唯一的解决方法是仔细检查在报告崩溃之前执行的其他代码。

另一种可能性是构建过程被搞砸了,并且包含了表现出旧错误的函数的过时实现。尝试做 "make clean" 和 "make build".

第三种可能性是代码在调试和生产设置中做不同的事情。例如,#ifdef DEBUG ... #endif 中包含的代码仅在调试时处于活动状态。此类代码常用于产品"debugging output"。它还会导致程序中内存布局的变化,从而影响指针误用的症状。

在你描述的场景中,也有可能是类型转换无效。将 char 指针转换为指向 X 的指针时,隐含地假设 X 具有特定大小是很常见的。问题是(除了 char 类型)所有类型的大小都是实现定义的。当使用不同的编译器重建代码时,这种不匹配(例如编写流的程序和解释它的程序假设大小不同)是潜在的罪魁祸首。 [这并不能解释在调试和生产设置中出现和消失的症状,但这是一个需要研究的潜在原因]。

找到。一个很难看到的分号终止了条件;我每次都在打条件体。使用更好的指针算法更正了进一步的堆损坏,"realloc(buff, size)" 应该是 "buff = realloc(buff, size)".