调试堆栈损坏

时间:2011-09-03 16:19:36

标签: c++ visual-studio debugging stack-corruption

现在我正在调试一个大型项目,它有一个堆栈损坏:应用程序失败。

我想知道如何使用Visual Studio 2010查找(调试)此类堆栈损坏代码?

以下是一些导致堆栈问题的代码示例,如何找到此类腐败的不太明显的案例?

void foo()
{
    int i = 10;
    int *p = &i;
    p[-2] = 100;
}

更新

请注意,这只是一个例子。我需要在当前项目中找到这样糟糕的代码。

3 个答案:

答案 0 :(得分:5)

有一种技术可以对这些类型的错误非常有效,但它只适用于具有一些特征的一部分:

  • 腐败值必须是稳定的(例如,在你的例子中,当腐败发生时,它总是100),或者至少可以用简单的表达式识别的东西
  • 腐败必须发生在堆栈上的特定地址
  • 腐败的价值非常不同,以至于你不会受到大量误报的打击

请注意,乍一看似乎不太可能出现第二种情况,因为根据运行时操作,堆栈可以以多种不同的方式使用。但是,堆栈使用通常非常确定。问题是特定的堆栈位置可以用于许多不同的事情,问题实际上是第3项。

无论如何,如果你的bug有这些特性,你应该识别出被破坏的堆栈地址(或者其中一个),然后设置一个内存断点来写入该地址,条件是只有当它被破坏时写的价值是腐败价值。在Visual Studio中,您可以通过在“断点”窗口中创建“新数据断点...”然后右键单击断点来设置条件来完成此操作。

如果最终得到太多的误报,可能有助于缩小断点的范围,方法是将其禁用,直到执行路径中的某个点更接近错误(如果您可以识别这样的时间),或者将命中数设置得足够高,以消除大多数误报。

另一个复杂因素是堆栈的地址可能会在运行之间发生变化 - 在这种情况下,您必须注意在每次运行时设置断点(地址的低位应该相同)。

答案 1 :(得分:2)

我相信你的问题引用了一个堆栈损坏的例子,你问的问题不是它崩溃的原因。

如果是这样,它会崩溃,因为它会创建未定义的行为,因为索引-2指向未知的内存位置。

回答关于剖析申请的问题:
您可以使用 Rational Purify Plus 来查看内存过载和访问错误。

答案 2 :(得分:-1)

这是UB:p[-2] = 100;

您可以使用此operator[]方式p[i]访问p,但在这种情况下,i是无效值。因此p[-2]指向无效的内存位置并导致未定义的行为。

要找到它,你应该调试你的应用程序并找到它崩溃的地方,并且希望它会出现在某个地方出现问题的地方。