12

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

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

这是导致堆栈问题的一些代码示例,我如何找到这种类型的损坏不太明显的情况?

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

更新

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

4

3 回答 3

5

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

  • 破坏值必须是稳定的(例如,在您的示例中,当发生破坏时,它始终为 100),或者至少可以通过简单的表达式轻松识别
  • 损坏必须发生在堆栈上的特定地址
  • 破坏值非常不寻常,以至于您不会受到大量误报的打击

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

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

如果你最终得到太多误报,它可能有助于缩小断点的范围,方法是让断点处于禁用状态,直到执行路径中更接近错误的某个点(如果你能确定这样的时间),或者设置命中计数足够高以消除大部分误报。

另一个复杂的问题是堆栈的地址可能会随着运行而改变——在这种情况下,您必须注意在每次运行时设置断点(地址的低位应该相同)。

于 2011-09-03T17:10:55.373 回答
2

我相信您的问题引用了堆栈损坏的示例,而您要问的问题不是它崩溃的原因。

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

要回答有关分析应用程序的问题:
您可以使用Rational Purify Plus for Visual Studio 来检查内存覆盖和访问错误。

于 2011-09-03T16:22:36.340 回答
-1

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

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

要找到它,您应该调试您的应用程序并找到它崩溃的地方,并希望它会在实际出现问题的地方。

于 2011-09-03T16:22:09.343 回答