【问题标题】:Incorrect watch values in Visual Studio 2010 ProfessionalVisual Studio 2010 Professional 中的监视值不正确
【发布时间】:2011-11-08 18:39:06
【问题描述】:

我遇到了一个非常奇怪的问题,其中某些变量的监视窗口值似乎与它们的“真实世界”值不匹配。调试器似乎在空间中关闭。这是显示它的最小代码sn-p:

printf("%d", pNodes[nNode].nColumn); // watch shows "4"
printf("%d", nColumn); // watch shows "1"

if (pNodes[nNode].nColumn != nColumn)
  continue; // this is NOT called

所以这是行为:

  1. 如果我将手表添加到pNodes[nNode].nColumn,它会显示4 的值。
  2. 如果我向nColumn 添加手表,它会显示1 的值。
  3. 如果我在监视窗口中检查表达式 pNodes[nNode].nColumn != nColumn,它的计算结果为 true
  4. continue 语句被跳过!
  5. 我添加了printf() 调用以查看发生了什么,printf() 打印值11,这似乎与代码“流动”的方式一致(即确实如此if 语句中调用continue

我什至可以检查&pNodes(nNode].nColumn 的内存,内存显示监视窗口显示的“不正确”值。因此,调试器似乎与实际程序数据或其他东西完全“断开连接”。我正在运行调试构建优化已关闭。我还检查了 pNodes 与某个全局变量或范围更高的其他变量不对应——似乎只有一个本地版本。

这对我来说完全莫名其妙!我什至不确定下一步该去哪里试图找出问题所在。如果您有任何想法,我很乐意听到!

谢谢!

【问题讨论】:

  • 我注意到 Visual Studio 有时似乎会与手表中的数组混淆,并显示第一个对象的成员。
  • 您确定您没有调试发布版本吗?如果你printfnNode&pNodes[nNode] 的值,它们是否与调试器所说的一致?
  • @Adam Rosenfield 是的,绝对是调试版本。不,printf 值确实与调试器监视值一致。我试图在第五点表达这一点。调试器监视值与程序正在使用的“实际”值不一致。
  • 如果你放置一个断点并尝试在中间窗口(不是监视变量)中计算表达式,它会说什么?

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


【解决方案1】:

Visual Studio 2010 调试器在跟踪监视变量内存位置方面存在问题。有时它会严重误导您,因为 VS2010 没有向您显示您认为它向您显示的变量。

例如,如果您在函数中重复使用变量名,那么随着执行范围的变化,应在监视窗口中显示哪个内存位置:

for (int i=0; i<10; i++) {
   i=i+1; // do something, what isn't important
}

int i;
for (i=0; i<5; i++) {
  i=i+1; // do something 
}

printf("i=%d\n", i);

现在将变量 i 放在监视窗口中。

显然,哪个 i(或值)显示在监视窗口中很重要。 如果你运行程序,你会看到当它进入 for 循环时,手表会跟踪 for 循环的 i 变量。当它退出 for 循环,然后使用另一个同名变量点击下面的代码时,监视窗口不会跟踪该变量的内存。

你会看到监视窗口仍然声明 i 是 10,即使在第二个循环中我现在是 0,1,2,...并且在第二个循环之后我实际上是 6,但监视窗口仍然声明 i是 10。

监视窗口应该做什么?我会争辩说,它应该始终向您显示具有该手表名称的变量的值,即在范围内,因为语言规则告诉您在任何给定时间只有一个变量在范围内。

这是调试器的监视窗口功能中的一个错误(VS2010 似乎只需在函数中找到与您在监视中指定的名称相匹配的第一个变量,并顽固地监视该内存空间,不管其他可能是什么在代码中,即使具有相同名称的新变量已经接管了作用域(此时监视窗口正在欺骗您!)

【讨论】:

  • 也发生在唯一命名的变量上。当公共数据在两个翻译单元中的定义不同并且更改的定义进入 PDB 时,就会发生这种情况。如果 VS 报告不一致,那就太好了。
  • 再想一想,作用域也会混淆符号信息;太糟糕了,该网站说我无法撤消我的反对票。
【解决方案2】:

所以我想我已经破案了:罪魁祸首是 Struct Member Alignment。我有一堆项目混合在一起,其中一些项目在项目中的这个字段具有不同的值。我删除了所有这些设置,让 VS 选择默认值,问题就消失了。

适用的值在某些项目中介于 4 字节 之间,在某些项目中为 默认,而在其他项目中则完全为空。该值位于Configuration Properties/C/C++/Code Generation/Struct Member Alignment下。同样,我最终只是完全删除了项目的值。我认为这是在过去的某个时候在项目上设置的,以处理某种跨平台问题,但至少它对于我现在正在做的工作是固定的!

感谢您的所有帮助!

【讨论】:

  • 这实际上违反了单一定义规则;头文件中的结构将根据不同的对齐规则进行编译。一个信号类型最终会在一个进程中具有不同的大小;显然调试器会对此感到困惑(不管数组会发生什么)
【解决方案3】:

如果使用不在范围内的变量设置监视,那是我在 Visual Studio 中经常看到的那种行为。它真的应该说“”或更有用的东西。

如果您在单步执行这些代码行时仍然看到那些幽灵般的值,我不知道:您确定这是一个调试版本吗?

【讨论】:

  • 是的。除了优化和代码生成设置之外,我还可以检查哪些其他值来验证它是调试版本?
  • @aardvarkk:可能会删除 release build 目录中的文件,以确保它不会以某种方式运行这些文件。
猜你喜欢
  • 1970-01-01
  • 2011-07-13
  • 2011-11-26
  • 2011-10-14
  • 2015-02-11
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多