在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
这里还要再介绍几个调试技术。大家使用这些调试技术,能使调试程序的工作变得更容易。 当程序运行时跟踪程序的执行有时对用户是很有帮助的;也许用户希望在不使用断点来暂停程序执行的情况下查看变量的值。使用OutputDebugString函数就能做到这些。这个函数是个使用方便的调试工具,但很多程序员却忽视了它,主要原因是对它介绍的不够。观察下图中Event Log窗口的最后一个入口,这一入口是用下面的代码生成的: procedure TForm1.btn1Click(Sender: TObject); begin OutputDebugString('In the btn1Click method...'); end; 这就是全部要做的。由于Delphi是系统调试器,因此,任何用函数OutputDebugString发送的字符串都会出现在Event Log窗口。可以在代码中任何位置调用OutputDebugString函数。 要查看一个变量的值,必须按格式构成字符串,并把字符串发送给OutputDebugString函数,例如: 运行程序后,点击btn1后,Event Log中显示如下: 使用OutputDebugString函数可以查看程序运行的整个过程,即使是对实践要求严格的代码段。
追踪查找存取违例当一个程序试图往不属于它的内存写入数据时,Windows会发出一条“Access Violation(存取违例)”出错消息。所有的Windows程序员在开发应用程序时,都碰到过存取违例错误。
不论是初学者还是经验丰富的Windows程序员,要追踪查找存取违例,都是一件困难的事情。但是,随着编写Windows程序的经验积累,程序员会逐渐对存取违例原因的查找产生产生第六感。下面讲述一些线索供大家在查找违例时参考;并不是只有这些情况才会使程序产生存取违例,但它们是最常见的情况。 1、未初始化指针未初始化指针是已经在程序中声明过的指针,但还未给它赋一个有意义的内存地址值。未初始化指针包含的是随机数据,最好的情况是它指向内存中无关紧要的地址,最坏的情况是它指向用户程序所在的内存中的某个单元,这样会导致不稳定的程序动作,因为每次运行程序时该指针可能指向不同的内存单元。应当在使用一个指针前和指针所指对象被删除之后将该指针设置成nil(空指针)。当存取一个空指针时,程序会停止运行并报存取违例,调试器加亮显示出错源代码行,这样用户就能立即查出有问题的指针。 2、删除前面已删除的指针删除一个已经被删除的指针会导致存取违例。应该将已删除的指针设成nil(空指针);删除一个空指针是十分安全的。把删除过的指针设置成nil(空指针),再删除这个指针时就保证不会出错。 3、数组覆盖(Array Overwrites)覆盖一个数组的末尾可引起存取违例。在有些情况下,被覆盖的内存不是关键性的,不会马上显现出问题,但过后不久程序还是因故障而停止运行。当这种情况发生时,用户很可能到程序停止运行的地方去查找故障,但问题实际上是出在程序的其他地方。另外一种情形是:被覆盖的内存很关键,因而程序会因故障而立即停止运行。极端情况下会造成Windows被破坏。 可通过范围检查把数组覆盖的可能性减少到最低程度。当设置检查范围时(缺省设置),编译器会对每一次数组引用作检查,看看看所存取的数组元素是否超出了有效范围。例如,下面这段代码就会导致编译器报错: 这段代码中要存取一个数组的30号元素,而此数组只有21个元素。编译器会检查出被存取的数组元素超出了数组声明的范围,并产生一个编译器错误,出错信息如下: 但是,检查范围对变量无效。例如,下面的代码就不会导致编译报错: 在这段代码中,尽管数组覆盖了9个字节,却不会产生编译错误;这是因为在编译时,编译器不知道变量X的值。 4、程序终止时存取违例当正常关闭一个程序时发生存取违例,一般都说明堆栈设置的太小。尽管在32位程序中这种情况发生的可能性不大,但在极端情况下也会发生。就像前面讲过的删除一个已被删除的指针,也可能引起程序终止时存取违例。 调试快速提示除前面给出的许多提示外,还要补充一下提示:
还有一个提示就是,当调试程序时,可使用一个内存检查程序。第三方的内存检查程序用于检查用户应用程序有无内存泄露。当用户将应用程序投入实际使用时,这类程序能省去许多麻烦。当应用程序存在内存泄露时,在使用该应用程序的过程中就会出问题。早起发现并排除内存泄露,无疑可大大节省用户的时间和精力。 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论