内存调试工具Electric Fence
程序中的内存越界读写会带来严重的问题,虽然有时问题不会立刻表现出来,但会埋下严重的隐患,总会有一天程序会莫名的崩溃,而且这种问题调查起来会很吃力。Efence(Electric Fence)可以在debug阶段帮我们最大程度的发现这种问题,并精确定位问题的所在。
Efence有2个主要的功能:
1. 内存越界读写时抛出segmentation fault。当程序用malloc申请内存时,Efence会使用虚拟内存技术将分配的内存空间之后的内存页面设置为inaccessible(不可读写和执行),所以当程序发生越界读写时,OS会发出SIGSEGV信号,生成core文件(core dump),进程退出。
2. 当访问已经被释放的内存空间时抛出segmentation fault。当程序把一块空间free之后,Efence同样把这块内存的访问保护级别设置为inaccessible,所以当程序再次访问这块已经释放的内存时也会导致segmentation fault。
可以通过配置以下几个全局变量和环境变量来控制Efence的行为:
1. EF_ALIGNMENT:这是Efence malloc分配空间的内存对齐字节数。这个变量的默认值是sizeof(int),32位字长的CPU对应的该值是4。这个值也是Efence能够检测的内存越界的最小值。
2. EF_PROTECT_BELOW: 默认情况下Efence是把inaccessible的页面置于分配的空间之后,所以检测到的是高地址方向的越界访问。把这个值设为1可以检测到低地址的越界访问。
3. EF_PROTECT_FREE: 通常free后的内存块会被放到内存池,等待重新被申请分配。把这个值设为1后,free后的内存块就不会被重新分配出去,而是也被设置为inaccessible,所以Efence能够发现程序再次访问这块已经free的内存。
4. EF_ALLOW_MALLOC_0: Efence默认会捕捉malloc(0)的情况。把该值设为1后则不会捕捉申请0字节内存的情况。
5. EF_FILL: 分配内存后Efence会将每一byte初始化成这个值(0-255)。当这个值被设成-1时,内存的值不固定。
Efence使用时需要库文件libefence.a,具体使用如下:
1. 查看并设置linux core文件的大小:
[root@RD22-TS root]# ulimit -c
0
[root@RD22-TS root]# ulimit -c 10000
或
[root@RD22-TS root]# ulimit -c unlimited
2. 如果已经安装Efence,编译时直接链接efence库:
gcc –g –o ef ef.c –lefence
如果没有安装Efence,则需要指定libefence.a的位置:
gcc –g –o ef ef.c –lefence –L /usr/lib
3. 当发生segmentation fault时就会在当前目录下生产一个core文件,在linux下,我们可以使用GDB来调试core:
Gdb ef core.xxxx
然后输入where就可以看到程序崩溃时的函数调用堆栈信息了。
ZebOS也支持Efence,在配置文件ZebOS5/config.opt/ZEBOSLNL2L3MCASTMPLS-IMISH中打开选项--enable-efence,并应用配置文件./config.opt/ZEBOSLNL2L3MCASTMPLS-IMISH-EF,接着打开config.log文件并查看Efence是否被正确配置,然后再编译就OK了。官方版本名字中带EF字样的都是支持EF的,如:ZebOS-7-8-2-ZEBOSLNL2L3MCASTMPLS-IMISH-EF-LINUX2.6.27.tar.gz
参考文件
Linux man page:man efence 或 http://linux.die.net/man/3/efence