現在的位置: 首頁 > 黃專家專欄 > 正文

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 等設計可能會更好一點。

抱歉!評論已關閉.