利用调用栈进行调试的策略

在不同的开发环境中,如Eclipse或Visual Studio,有许多关于如何访问调用栈的信息。然而,关于如何实际理解调用栈的信息却相对较少。本文将介绍一种使用调用栈进行调试的策略。将以一个用C++编写并在Visual Studio 2012中开发的个人项目为例,但会尽量提供适用于其他编程语言和IDE的通用策略和结论。对于经验丰富的程序员来说,这里提供的信息可能看起来微不足道,但对于没有从更资深的同事那里了解到这种技术的人来说,这些信息可能是至关重要且难以找到的。

步骤1:遇到bug -> 找到它出现的地方

在运行项目的一个测试时,抛出了以下异常:

异常清楚地表明它是在函数getPixelFromMiddle()的第116行抛出的,该函数位于ColorBox.cpp中。在第一步中,找到抛出异常的代码行是一个简单的任务。在定位到这行代码后,在其上设置一个断点。这是bug出现的地方,所以将需要使用调用栈深入代码中找到导致它的冲突状态。

如果程序崩溃而没有明确指出发生了意外,使用断点并在几次测试运行中改变它们的位置,以找到程序崩溃的代码行。

步骤2:查看调用栈

在正确的位置设置断点后,再次以调试模式运行程序。执行在断点处停止。导航到调用栈窗口(在VS中,通过菜单Debug -> Window -> Call Stack),将看到调用彼此的函数的堆叠列表。函数ColorBox::getPixelFromMiddle()位于栈顶,因为这是程序执行停止时最后一个被调用的函数。ColorBox::getPixelFromMiddle()下面的函数是它的调用者,VS标记了程序执行在从getPixelFromMiddle()返回后将恢复的代码行。

示例中的调用栈有以下条目: ColorBox::getPixelFromMiddle()Schlieren::colorFinalImageAt()调用,它又被Schlieren::generateFinalImage()调用,它又被Test::schlierenProcessing()调用。 访问调用栈,可以检查程序执行在某一时刻冻结的情况,显示其所有内部细节。

步骤3:检查调用栈

现在可以使用调用栈调试的强大功能。在调试时,调用栈提供了两种不同类型的信息。首先,有程序执行序列,可以检查应用程序的实际业务逻辑是否符合意图(当调试自己的代码时)。第二件重要的信息是程序状态,即在程序执行达到断点时所有变量和对象持有的值。使用在编辑器中可用的最喜欢的技术来检查感兴趣的变量的值(在VS中,通过将鼠标悬停在它们上面或使用Autos、Locals或Watch窗口等)。

现在拥有所有信息,可以进行快速而简单的调查,找到导致异常触发的状态冲突(bug)。

在示例中,异常抛出是因为变量w持有一个值为65531的值。w是处理图像时的当前宽度值,因此它应该在0和图像宽度之间。它是uint16_t类型,所以最大值是65535。65531的值非常接近uint16_t类型的最大值,这表明试图将负值-5分配给这个无符号变量,结果为65531(65536-5)。宽度应该是一个非负数,所以状态冲突是在将值-5分配给w的代码行。

使用调用栈回溯到上一个函数:Schlieren::colorFinalImageAt()(在栈上点击getPixelFromMiddle()下方的它)。 当鼠标指针悬停在用于调用getPixelFromMiddle()wOffset上时,可以看到它确实有-5的值。已经识别出了bug。在调用代码(colorFinalImageAt())中,调用getPixelFromMiddle(wOffset = -5, hOffset = 4),而它的签名是getPixelFromMiddle(uint16_t w, uint16_t h)。给无符号整型变量负值导致了状态冲突。

注意:请注意,bug可能比示例中显示的要远离它出现的地方。只使用这个简单但真实的例子来展示调用栈调试的策略,而不会过多地涉及特定代码体的技术细节。

步骤4:解决状态冲突

找到导致状态冲突的代码逻辑不一致性几乎会自动产生解决方案。类ColorBox持有一个大小为m_size X m_size的正方形RGB图像(成员变量m_colorData)。成员函数getPixelFromMiddle(uint16_t w, uint16_t h)接收一个宽度和高度值。这些包含从图像中间偏移的宽度和高度值。因此,它们可以持有负值,所以它们应该是有符号整型。除了改变类型外,还有一个更微妙的变化要做:两个函数参数应该在getPixelFromMiddle()中重命名为wOffsetFromMiddlehOffsetFromMiddle。如果从一开始就使用这些名称,那么它们应该是有符号整型就会变得很明显。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485