首页 > *nix技术, 内存管理, 跟踪调试 > 踩内存检测

踩内存检测

2011年12月1日 发表评论 阅读评论 10,452 次浏览

众所周知,踩内存是一个非常麻烦的问题,不管是在应用层或是内核层,关于踩内存的检测也有各种各样的工具,比如应用层的优秀开源valgrind,内核内置的kmemcheck等。关于这些工具的具体信息就不在这里做进一步描述了,本文主要简单介绍一下几种踩内存工具的工作原理。

一种最为简单的踩内存工具为通过给分配的内存前后多加上一小块内存,用于存放我们预先设定的值,比如Crc和Magic:

不管是应用程序(App)或是内核模块(Module),它们分配内存都是利用我们重载过的接口(malloc或kmalloc或new或其它等),这些接口分配比实际请求要大一点的内存,以便在前和后能空留出一个或几个字节存放检测值(也就是前面提到的Crc和Magic)。Magic可以是我们预先指定的特定值,比如0xC0,而Crc可以是某些条件(比如当前请求内存分配的进程的id、名、代码行等)的crc值。应用程序或是内核模块释放内存同样也是利用我们重载过的接口(free或kfree或delete或其它等),在这些接口里就可以做踩内存检测,如果发现Magic不再是我们预先指定的特定值,比如0xC0,则表示该块内存被踩了,而Crc呢?虽然没有固定的值,但也可以通过做同样的计算后做对比检测,或者我们还可以提前在分配内存时把这些值记录下来,比如可以设置一个hash表,把App id/name, Code line,Module id/name, Code line …和对应的Crc存起来,通过扫描Crc是否存在来做判断,也可以通过这个hash表做Crc反查到对应的进程和模块。

可以看到这种方法的缺点就是发现踩内存比较慢,要等在内存释放时才能检测获知。所以,可以提供一些proc接口以便随时通过命令显示内存当前使用情况。
另一种可以实时检测到踩内存的做法很巧妙,在codeproject上有详细的英文介绍,下面也再介绍一下。应用程序(App)或是内核模块(Module)对内存的分配释放接口仍然由我们重载,这无需多说,它的主要思路就是不管应用程序(App)或是内核模块(Module)申请多么小的内存,我们都直接给它分配2个页面(这里先讨论实际申请的内存块小于1页的情况),而这块实际内存块在这2个页面里怎么放呢?有两种放法:

第一种(左)是把实际请求内存块放在第一页的末尾,而把第二页设置为只读,此时如果往后越界必定踩到第二页,而由于该页为只读属性,于是立即被OS弹出异常。
第二种(右)是把实际请求内存块放在第二页的开始,而把第一页设置为只读,此时如果往前越界必定踩到第一页,而由于该页为只读属性,于是立即被OS弹出异常。
可以看到,这两种情况都只能检测前向和后向中的任何一种越界,而对于相应的另一种就无能为力。如果实际申请的内存块大于1页的时也是如此(如下图,大于1页,小于2页的情况,其它类似),除非实际申请的内存块恰好为内存页整数倍(包括其它额外开销所占的内存),也许可以在前后都设置只读页。但是,我们有办法解决这个问题,那就是提供参数可以用于指定是进行前向越界检测还是后向越界检测,而实际程序/模块踩内存检查时,同时跑两个相同内核模块(可能需要两台机器)或两个相同应用程序,一个进行前向越界检测,一个进行后向越界检测,因为只要越界踩内存必定被OS抓出来,所以这种办法也算是可行的。

前面提到的两种方法对越界踩内存的检测比较可行,但对于随机踩就看运气了,而且运气还要比较好才行。而顺带说一下的第三种做法就是延用上面第二种方法的思想,把OS里没用到的内存都设置为只读,提高这种运气的可能性,然后就是念经拜佛,希望踩内存的那行代码,就给我踩到只读内存页,被OS抓出来吧。

转载请保留地址:http://www.lenky.info/archives/2011/12/446http://lenky.info/?p=446


备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。

法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以Email或书面等方式告知,本站将及时删除相关内容或链接。

  1. 搞复杂了
    2013年3月28日21:47 | #1

    一两句说清楚的,何必搞那么多东西

  1. 本文目前尚无任何 trackbacks 和 pingbacks.