调试堆栈损坏
Posted
技术标签:
【中文标题】调试堆栈损坏【英文标题】:Debug stack corruption 【发布时间】:2011-09-03 16:19:36 【问题描述】:现在我正在调试一个有堆栈损坏的大型项目:应用程序失败。
我想知道如何使用 Visual Studio 2010 查找(调试)此类堆栈损坏代码?
这是导致堆栈问题的一些代码示例,我如何找到这种类型的损坏不太明显的情况?
void foo()
int i = 10;
int *p = &i;
p[-2] = 100;
更新
请注意,这只是一个示例。我需要在当前项目中找到这么糟糕的代码。
【问题讨论】:
代码示例的用途是什么?您是在问为什么这会破坏堆栈? 你需要偷偷摸摸地解决问题,所以它看不到你。这可能是很多工作。但本质上,一次又一次地跑,越来越接近坏事发生的地方。添加跟踪语句会有很大帮助。 /RTC 选项添加调试代码以诊断堆栈问题。我怀疑它会捕捉到这个特定的错误,它不会破坏堆栈框架。 我通常调试应该可以工作的代码中的问题,以便找出问题所在。但是,我通常不会浪费时间调试我确定它绝对错误且不应该工作的代码。但如果是出于教育目的,请继续尝试使用损坏的代码。 :) 通常调试项目已经有 /RTC1 活动... 【参考方案1】:有一种技术可以非常有效地解决这些类型的错误,但它只适用于具有一些特征的其中一部分:
损坏的值必须是稳定的(例如,在您的示例中,发生损坏时始终为 100),或者至少可以在简单表达式中轻松识别的值 损坏必须发生在堆栈上的特定地址 损坏的值非常不寻常,您不会受到大量误报的影响请注意,第二个条件乍一看似乎不太可能,因为堆栈可以根据运行时操作以多种不同方式使用。但是,堆栈的使用通常是非常确定的。问题是一个特定的堆栈位置可以用于许多不同的事情,问题实际上是第 3 项。
无论如何,如果您的错误具有这些特征,您应该识别被损坏的堆栈地址(或其中一个),然后设置一个内存断点以写入该地址,条件是只有在写入的值是破坏值。在 Visual Studio 中,您可以通过在“断点”窗口中创建“新数据断点...”然后右键单击断点来设置条件来执行此操作。
如果您最终得到太多误报,可能有助于缩小断点的范围,方法是让断点处于禁用状态,直到执行路径中更接近错误的某个点(如果您可以识别这样的时间),或者将命中计数设置得足够高以消除大部分误报。
另外一个复杂的问题是堆栈的地址可能会随着运行而改变 - 在这种情况下,您必须注意在每次运行时设置断点(地址的低位应该相同)。
【讨论】:
【参考方案2】:我相信您的问题引用了堆栈损坏的示例,而您要问的问题不是它崩溃的原因。
如果是这样,它会崩溃,因为它创建了一个未定义的行为,因为索引-2
指向一个未知的内存位置。
要回答有关分析您的应用程序的问题: 您可以使用 Rational Purify Plus for Visual Studio 检查内存覆盖和访问错误。
【讨论】:
谢谢,但根据wiki 它不支持 Visual Studio 2010。【参考方案3】:这是 UB:p[-2] = 100;
您可以使用operator[]
以这种(p[i]
)方式访问 p,但在这种情况下,i
是无效值。所以p[-2]
指向一个无效的内存位置并导致未定义的行为。
要找到它,您应该调试您的应用程序并找到它崩溃的地方,并希望它会出现在实际出现问题的地方。
【讨论】:
事实上,您可以在指向非数组对象的指针上使用[]
:它们被视为指向单个元素数组的指针。当然,一个元素的数组没有索引-2。
这能回答 OP 的问题吗?
我认为 OP 需要更好地表述他的问题,不确定他在问什么。以上是关于调试堆栈损坏的主要内容,如果未能解决你的问题,请参考以下文章