📄 g5.htm
字号:
死机(在Windows系统中有时是“非法指令”错)错误很主要的来源来自指针,但这并 <br>
不是说我们就不能使用指针。恰恰相反,我们在很多地方都使用指针,而且出错的机会很 <br>
少。原因很简单,那是因为我们在使用被保护的指针。如果你能证明你所使用的指针永远 <br>
都指在合法的位置上,它还会出错么?所以我们在分配空间时大多使用静态空间和连续空 <br>
间。所谓静态空间就是数组,连续空间就是指针数组。我们通过数组的下标来限制指针的 <br>
读取,这样非常方便也有效。 <br>
封装也是减少错误的很好办法。我们把对内存的分配和释放封装起来,把对全局量的 <br>
读取封装起来。在查找问题时就可以很快地缩小可疑对象。 <br>
对函数的返回值和错误代码的认真对待也可以让我们飞快地找到问题所在。很多人刚 <br>
开始编程时都认为程序很短小,没必要写那么复杂的错误处理信息,也没必要判定函数的 <br>
返回值。而我则恰恰相反,无论对待多么简单的程序我都会做非常详尽的错误处理。我甚 <br>
至把显示错误的对话框写在底层程序中,以供随时调用。假如出现了错误,我就可以迅速 <br>
知道错误发生的位置以及发生错误的大概原因,我的程序还可以正常地退出,不是继续执 <br>
行而造成死机。 <br>
使用调试信息可以帮助我在Debug版中获得更多的有用信息。比较常用的有Assert() <br>
和OutputDebugString()。在错误刚刚发生时就拦截它要比它造成了更严重的影响后要好 <br>
。 <br>
代码写得好看一些也有助于查错。假如你在一行中写进好几句代码,你将如何逐行跟 <br>
踪呢?我们如果把函数,成员函数写得规范对称,虽然麻烦一些,但别人在使用时就会轻 <br>
松多了。 <br>
<br>
这些办法都是在我们编写代码时需要注意的内容,我想如果你在准备开始编程时就对 <br>
此有所准备,那么到你编程结束时应该能够节省不少调试错误的时间。但是Bug是一定会 <br>
有的,无论你在当初如何注意,因为我们毕竟是人,会犯错误。我想任何人都有过把恒等 <br>
号(双等于号)写成赋值号(单等于号)的经历吧(好在在Visual C++ 6.0中有这方面的警告 <br>
了)。没有别的办法,我们仍然需要面对死机。一般的指针错误只会导致“非法指令”或 <br>
“未知的意外”错误,除非你向一个不知名的地方写了大量的内容(比如几百K以上),一 <br>
般还是可以安全地退到系统中的。这得非常感谢微软,Windows95/98还是要比DOS好。可 <br>
是如果你所访问的是系统区域,或申请了与硬件有关的调用,比如在DirectDraw的 <br>
GetDC()中设置了断点,程序就会直接退回系统或干脆死机。 <br>
这个时侯就全凭我们自己了。但是也不要害怕,因为,我们所面对的仅仅是一些代码 <br>
而已,我们有一个最为严格和伟大的力量:逻辑。这可能是程序员唯一能够全心全意依靠 <br>
的力量了。所以请大胆地使用它。 <br>
如果程序出错,一定有它的道理。哪怕运行一千次只出现一次也是如此。所以我们改 <br>
正错误的过程实际上也就是找到错误的过程。如何找到错误呢?可以试着用下面的方法: <br>
<br>
屏蔽法:把一些代码去掉,再看错误是否消失了,如果已经消失,那么错误可能在刚 <br>
才屏蔽掉的代码中,再屏蔽掉另外的代码,如果错误又出现了,则错误肯定在这段代码中 <br>
。要注意的是,这样做不一定能够找到错误,因为,有时侯错误是由两段代码或多段代码 <br>
相互影响造成的。而且有的时侯我们找到的地方可能并不是真正出错的地方,你只找到了 <br>
错误被引发的地方,而引发错误的地方还需要我们再仔细找。比如,一个指针指错了地方 <br>
,那么我们会发现出错的地方是引用指针的地方而不是写入指针的地方。这时侯就体现出 <br>
封装变量的用处来了,我们可以很快查出这个指针到底在哪被修改了。 <br>
如果上面的方法不能奏效,而且错误是在我们刚刚修改了代码造成的,那么可以使用 <br>
比较法,找到原来版本的文件进行比较。所以我们需要经常保存备份程序,一方面是为了 <br>
保证程序不丢失,另一方面也会增加找到错误的机会。尤其是当我们到了编程的后期,我 <br>
们的程序大都编完,正处于修改的状态,而时间又特别紧迫。如果一旦出现了错误,我们 <br>
只要比较一下新旧版本,就很容易找到错误。 <br>
如果你跟踪了半天也没有结果,几网下去一条鱼也没捞上来,而且必须在全屏状态运 <br>
行,不能单步跟踪,每执行一遍程序就死机,又需要重新启动,这又该怎么办呢?那也不 <br>
要担心,我们还有最后一招:输出Log文件。在每一个需要监视的地方,增加一段程序, <br>
向磁盘文件输出一段文字,如果程序运行到这里,该文件就会多出一段文字,如果程序运 <br>
行到这里之前就死机或退出了,那么出错的地方就在这段文字和上段文字之间。虽然这样 <br>
做比较耗费时间和精力,但是基本上能够找到出错的地方。找到之后,我们再去找出错的 <br>
原因吧。 <br>
但是万一你现在还是没有找到错误该怎么办呢?那也不要着急,我所遇到的找到错误 <br>
的最长时间是整整一天,有的人会长达3天,但是我目前尚未遇到查找单个错误的时间超 <br>
过一个星期的。如果你寻找错误的时间还没有达到这个长度,就不要急于认为这个错误你 <br>
是永远找不到的。 <br>
<br>
其实最难找的错误并不是这些错误,因为这些错误是确实存在的,所以我们改正它只 <br>
是时间问题。而比较难以调试的错误并不是每次运行都出现的,有的错误需要特定的环境 <br>
和条件,比如只在某台计算机上出现,有的错误则需要特定的操作,比如打开某文件,再 <br>
关上,有的错误则干脆需要运行一定的时间才可能出现,比如运行一个小时。这时侯我们 <br>
的工作才真正艰巨起来。 <br>
这时侯,也往往是开发的最后关头,最紧张的时侯,如果出现了错误,将使我们直接 <br>
面临一个最严峻的问题,到底是发行时间重要还是修改程序错误重要。我姑且不谈到底谁 <br>
重要。关键是如何解决这些错误。这里你可以看到,把错误消灭于未然是多么重要。我们 <br>
工作的重点现在转向了重现错误。使用出错的计算机,频繁重复执行某些有关的操作,随 <br>
时存盘以保存最近时的信息,都是我们常用的办法。 <br>
有的时侯重新启动一次计算机,重新编译所有代码,更换一些驱动程序,都可以解决 <br>
问题。但是有些问题我必须说明: <br>
第一,要以负责任的态度来解决问题。如果你发现有一个地方很明显不会造成错误, <br>
但是修改一下之后错误确实消失了,这时侯千万要小心,因为这个错误可能这样被你又隐 <br>
藏起来了,在以后的某个时侯(可能是最后的调试期)再次出现,这时侯它将会更加隐蔽。 <br>
<br>
第二,不要动不动就认为是编译器,驱动程序,操作系统或计算机硬件有问题,而不 <br>
下功夫去寻找错误。这些东西确实会有问题,但它们出错的机会比起我们自己要小得多, <br>
我觉得初级程序员还很难发现它们的错误。有问题还是先从自己那里着手吧。 <br>
</td>
</tr>
</table>
<p align="center"> </p>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -