现在我正在调试一个有堆栈损坏的大型项目:应用程序失败。
我想知道如何使用 Visual Studio 2010 查找(调试)此类堆栈损坏代码?
这是导致堆栈问题的一些代码示例,我如何找到这种类型的损坏不太明显的情况?
void foo()
{
int i = 10;
int *p = &i;
p[-2] = 100;
}
更新
请注意,这只是一个示例。我需要在当前项目中找到这样糟糕的代码。
现在我正在调试一个有堆栈损坏的大型项目:应用程序失败。
我想知道如何使用 Visual Studio 2010 查找(调试)此类堆栈损坏代码?
这是导致堆栈问题的一些代码示例,我如何找到这种类型的损坏不太明显的情况?
void foo()
{
int i = 10;
int *p = &i;
p[-2] = 100;
}
请注意,这只是一个示例。我需要在当前项目中找到这样糟糕的代码。
有一种技术可以非常有效地处理这些类型的错误,但它只适用于具有一些特征的其中一部分:
请注意,第二个条件乍一看似乎不太可能,因为堆栈可以根据运行时操作以多种不同方式使用。但是,堆栈的使用通常是非常确定的。问题是一个特定的堆栈位置可以用于许多不同的事情,问题实际上是第 3 项。
无论如何,如果您的错误具有这些特征,您应该识别被损坏的堆栈地址(或其中一个),然后设置一个内存断点以写入该地址,条件是只有在写入的值是腐败的价值。在 Visual Studio 中,您可以通过在“断点”窗口中创建“新数据断点...”然后右键单击断点来设置条件来执行此操作。
如果你最终得到太多误报,它可能有助于缩小断点的范围,方法是让断点处于禁用状态,直到执行路径中更接近错误的某个点(如果你能确定这样的时间),或者设置命中计数足够高以消除大部分误报。
另一个复杂的问题是堆栈的地址可能会随着运行而改变——在这种情况下,您必须注意在每次运行时设置断点(地址的低位应该相同)。
我相信您的问题引用了堆栈损坏的示例,而您要问的问题不是它崩溃的原因。
如果是这样,它会崩溃,因为它创建了一个未定义的行为,因为索引-2
指向一个未知的内存位置。
要回答有关分析应用程序的问题:
您可以使用Rational Purify Plus for Visual Studio 来检查内存覆盖和访问错误。
这是UB:p[-2] = 100;
operator[]
您可以使用in this( p[i]
) 方式访问 p ,但在这种情况下i
是无效值。所以p[-2]
指向一个无效的内存位置并导致未定义的行为。
要找到它,您应该调试您的应用程序并找到它崩溃的地方,并希望它会在实际出现问题的地方。