第3章为子系统设防

第3章为子系统设防

ID:1878626

大小:89.50 KB

页数:23页

时间:2017-11-13

第3章为子系统设防_第1页
第3章为子系统设防_第2页
第3章为子系统设防_第3页
第3章为子系统设防_第4页
第3章为子系统设防_第5页
资源描述:

《第3章为子系统设防》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

1、第3章为子系统设防在上一章中我们说过瓶颈子程序是加入断言的绝佳之处,因为它可以使我们用很少的代码就能够进行很彻底的错误检查。这就好象一个足球场,虽然可以有50000个球迷来看球,但如果检票人员站在球场的入口,那么只需要几个检票人员就够了。程序中也有这样的入口,这就是子系统的调用点。例如,对于文件系统,用户可以打开文件、关闭文件、读写文件和创建文件。这是五个基本的文件操作,这些操作通常需要大量复杂代码的支持。有了这些基本的操作,用户就可以通过对它们的调用来完成相应的文件操作,而不必操心文件目录、自由存储空间映射或者特定硬件设备(如磁盘驱动器、磁带驱动器

2、或联网设备)的读写等实现细节。又如,对于内存管理程序,用户可以分配内存、释放内存,有时还可以改变分配了的内存的大小。这些操作同样需要许多代码的支持。通常,子系统都要对其实现细节进行隐藏,所隐藏的实现细节可能相当复杂。在进行实现细节隐藏的同时,子系统为用户提供了一些关键的入口点。程序员通过调用这些关键的入口点来实现同子系统的通讯。因此如果在程序中使用这样的子系统并且在其调用点加上了调试检查,那么不用花很大力气就可以进行许多的错误检查。例如,假如要求你为标准的C运行时间库编写malloc、free和realloc子程序(有时必须做这件事情),那么你可能会

3、在代码中加上断言。你可能进行了彻底的测试,并已编写了极好的程序员指南。尽管如此,我们知道在使用这些程序时,用户还是会遇到问题。那么为了对用户有所帮助,我们可以作些什么呢?这里给出的建议是:当子系统编写完成之后,要问自己:“程序员什么情况下会错误地使用这个子系统,在这个子系统中怎样才能自动地检查出这些问题?”在正常情况下,当开始编码排除设计中的危险因素时就应该问过了这个问题。但不管怎样,还应该再问一次。对于内存管理程序。程序员可能犯的错误是:l分配一个内存块并使用其中未经初始化的内容;l释放一个内存块但继续引用其中的内容;l调用realloc对一个内存

4、块进行扩展,因此原来的内容发生了存储位置的变化,但程序引用的仍是原来存储位置的内容;l分配一个内存块后即“失去”了它,因为没有保存指向所分配内存块的指针;l读写操作越过了所分配内存块的边界;l没有对错误情况进行检查。这些问题并不是臆想出来的,它们每时每刻都存在。更糟的是,这些问题都具有不可再现的特点,所以很难发现。出现一次,就再也看不到了。直到某一天,用户因为被上面某个常见问题搞得一筹莫展而怒气冲冲地打电话来“请”你排除相应的错误时,才会被再次发现。确实,这些错误都很难发现。但是,这并不是说我们没有什么可以改进的事情了。断言确实很有用,但要使断言发挥

5、作用就必须使其能够被执行到。对于我们上面列出的问题,内存管理程序中的断言能够查出它们吗?显然不能。在这一章中,将介绍一些用来肃清子系统中错误的其它技术。使用这些技术,可以免除许多麻烦。本章虽然以C的内存管理程序为例进行阐述,但所得到的结论同样适用于其它的子系统,无论是简单的链表管理程序,还是个多用户共享的正文检查工具都适用。若隐若现,时有时无通常,解决上述问题的方法是直接在子系统中加上相应的测试代码。但是出于两个理由,本书并没有这么做。第一个理由是我不想让例子中到处都是malloc、free和realloc的实现代码。第二个理由是用户有时得不到所用子

6、系统的源代码。我之所以会这么说,是因为在用来测试本书例子的六个编译程序中,有两个提供了标准的源代码。由于用户可能得不到子系统的源代码,或者即使能够得到,这些源代码的实现也未必都相同,所以本书不是直接在子程序的源代码中加上相应的测试代码,而是利用所谓的“外壳”函数把内存管理程序包装起来,并在这层包装的内部加上相应的测试代码。这就是在得不到子系统源代码的情况下所能采用的方法。在编写外壳函数时,将采用本书前面介绍过的命名约定。下面我们先讨论malloc的外壳函数。它的形式如下:/*fNewMemory───分配一个内存块*/flagfNewMemory(v

7、oid**pv,size_tsize){byte**ppb=(byte**)ppv;*ppb=(byte*)malloc(size);return(*ppb!=NULL);/*成功*/}该函数看起来比malloc要复杂,这主要是其指针参数void**带来的麻烦。但如果你看到程序员调用这一函数的方法,就会发现它比malloc的调用形式更清晰。有了fNewMemory,下面的调用形式:if((pbBlock)=(byte*)malloc(32)!=NULL)成功───pbBlock指向所分配的内存块else不成功───pbBlock等于NULL就可以被代

8、替为:if(fNewMemory(&pbBlock,32))成功───pbBlock指向所分配的内存块els

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。