只需要感兴趣的文件,并将它们与剩余的未检测的对象模块链接。但是,
在这样做时需要注意的是,它可能会导致
虚假的警告和错误消息,因为
代码
的未检测部分没有为它们使用的内存位置维护必要的运行时类型信息例
如,如果将对程序未配置部分中的有效对象的引用传递给插装函数,则该
工具将认为该对象未分配,并且如果该对象被引用,则可能输出虚假错误
消息。
这个问题通常会扩展到库模块。例如,像memcpy这样的函数中的值的初
始化,像
fgets
这样的函数中的输入值的初始化
,
以及像
ctime
这样的函数返
回的静态缓冲器中的数据类型都不会被捕获。为了处理这些问题,我们创
建了
一个通用库函数的插装版本的集合,这些库函数是
一个插装类型。这些是
原始函数的包装器,手写以在RTC镜像中执行必要的标记更新操作,
他们的典型行为。
这些插装库函数中包括内存管理函数.每次调用malloc(或它的一个亲
戚)都被替换为调用包装器版本,在成功分配内存块时,将该内存块的镜
像设置为
未初始化
。类似地,
free
函数的包装器版本将镜像重置为
未分配
。
malloc包装器还在已分配的块之间添加填充,以减少流浪指针从一个块跳到
另一个块的可能性(这是Purify [7]使用的方法)。
RTC工具能够检测某些SPEC基准测试(go、ijpeg)、Solaris实用程
序(nroff、col等)中的错误和Olden基准(健康,
voronoi)[10]。大多数
错误是越界数组或指针访问。
在
Solaris
实用程序中,越界访问导致程序崩溃
;
在SPEC情况下,错误对执行没有明显影响,这
使得在不使用RTC工具等工
具的情况下很难检测到错误。
在每种情况下,RTC工具都能够检测到越界内存访问,因为指向的内存类
型与预期的类型不同。
最后,RTC工具自然适合交互式调试。当发出警告或错误消息时,会发
送一个信号(SIGUSR1),并可以被GDB等交互式调试器拦截[17]。然后,
用户可以检查内存位置,包括镜像,并利用
GDB
3
消除不必要的检查
虽然RTC工具的初始实现证明了它能够如上所述在实际程序中发现错误,
但该实现的缺点是性能差:在最坏的情况下,