现在的位置: 首页 > 黄专家专栏 > 正文

Electric-fence 介绍

2014年10月30日 黄专家专栏 ⁄ 共 1725字 ⁄ 字号 评论关闭

一般情况下,程序出现 segmentation fault,可以有多种方法 debug,利用 log 能找出程序 90% 以上的 bug,剩下的简单一点可以采取二分法注释掉代码或者祭起 gdb 这个大杀器。但是有的时候,gbd 给出的 crash 上下文其实并不是真正发生问题的第一现场,在多线程程序设计中,这种情景会让 bug 的追查陷入误区。

介绍一个内存 debug 的工具, electric-fence。 我手头的版本是 2.1.13。

electric-fence 的原理是重写 malloc(3) 和 free(3), 多分配一个 page 在用户需要的内存空间之后,并且利用函数 mprotect(2) 将这个 page 写保护。

mprotect 函数的介绍如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
MPROTECT(2)                 BSD System Calls Manual                MPROTECT(2)

NAME
     mprotect -- control the protection of pages

SYNOPSIS
     #include <sys/mman.h>

     int
     mprotect(void *addr, size_t len, int prot);

DESCRIPTION
     The mprotect() system call changes the specified pages to have protection prot.  Not all implementa-tions implementations
     tions will guarantee protection on a page basis but Mac OS X's current implementation does.

     When a program violates the protections of a page, it gets a SIGBUS or SIGSEGV signal.

     Currently prot can be one or more of the following:

     PROT_NONE   No permissions at all.
     PROT_READ   The pages can be read.
     PROT_WRITE  The pages can be written.
     PROT_EXEC   The pages can be executed.

RETURN VALUES
     Upon successful completion, a value of 0 is returned.  Otherwise, a value of -1 is returned and errno
     is set to indicate the error.

ERRORS
     mprotect() will fail if:

     [EACCES]           The requested protection conflicts with the access permissions of the process on the
                        specified address range.

     [EINVAL]           addr is not a multiple of the page size (i.e.  addr is not page-aligned).

     [ENOTSUP]          The combination of accesses requested in prot is not supported.

可以看出,该函数只能操作对齐的 page, 控制该 page 是否能可读,可写,可执行。

所以,当通过 electric-fence 分配出的内存第一次被写越界的时候,直接报错退出。 这样,我们就可以发现错误的第一现场。

electric-fence 通过定义 EF_PROTECT_BELOW 设置对分配内存开头越界的保护, 由于 mprotect(2) 只能操作对齐的 page, 所以某块内存都头尾都加上一个 page 来检测写入越界显然是不可行的。

electric-fence 也有如下的缺点:

  1. 每一次分配都是利用一个 semaphore 同步,没有 thread local 的分配
  2. malloc 和 free 在 slot 都是线性查找,这也造成了整体性能的落后
  3. 内存消耗大,这个是显然的,特别对于频繁的小内存分配

2,3 点都是造成整个 lib 性能较低的原因。简单说,这还是一个比较简陋的工具,如果能借鉴 tcmalloc, jemalloc 等设计可能会更好一点。

抱歉!评论已关闭.