蘋果小豬研究室
  • 首頁
  • 中譯資料
  • 網路觀念
    • OSGi 平台
    • SCTP 通訊協定簡介
      • 1 多重串流 (Multi-streaming)
      • 2 路徑多宿 (Multi-homing)
      • 3 SACK 機制
      • 4 Path MTU Discovery
      • 5 Ordered/Unordered 傳送機制
      • 6. SCTP API
      • 7. TCP 與 SCTP 通訊協定比較
      • 8. 參考文獻
    • TCP over SCTP tunnel
    • TCP 與 SCTP 協定轉換機制
    • UPnP 與 UPnP AV
  • Linux 程式設計
    • [C] 產生亂數
    • [C] Pointer and array
    • [Script] strncmp
    • [C] Linux 取得 HD 序號
    • [C] 程式範例-切割 subnet
    • C struct 的使用
    • C 目錄相關
    • const 修飾詞
    • Dangling pointer(懸置指標)
    • dnsmole
    • dos2unix 程式碼
    • Function pointer in C
    • GCC header limits.h
    • GDB 參數
    • glibc detected (double free)
    • IEEE 754 and float 範例程式
    • kernel 中的網路卡名稱與命名順序關係
    • Linux 序列埠程式設計
    • loop device 的數目
    • Perl & LWP
    • Remote Control over CGI
    • 偵測 NAT 內部主機連線狀況
    • 利用 libpcap 取得所有的網路裝置名稱
    • 取得時間
    • strncpy
    • 從應用層程式取得傳輸層 TCP 資訊
    • 於 Linux 上撰寫 daemon server 要注意的
    • 為什麼需要 & 0377
    • 研究 setsid()
    • 與 HTTP 協定有關的 RFC
    • 製作 patch 檔
    • 設計在背景執行的 Linux 程式
    • 讀取 STDIN (Standard INPUT) 範例程式
    • 關於 Linux CPU smp_affinity
    • 陣列名稱與指標
  • 網路服務推薦
    • 專案管理工具 - clickup
    • 文件大師 - gitbook
  • glibc 中文手冊
    • GNU C 函式庫常見問題(FAQ)
  • Linux 系統操作
    • /proc/sys/net/ipv4/conf/eth* 目錄中的參數
    • Linux 伺服器效能調校
    • Linux 設定網卡速度
    • Proxy ARP
    • sysrq
    • Turn off beep in Linux system
    • umask()
    • 以 ethtool 查看網路卡狀態及設定
    • 使用 nameif 修改 Linux 網路卡名稱
    • 使用 xhost
    • 利用 sed 取出檔案中某行
    • 在 bash 中設定 Proxy server
    • 在 Linux 系統呈現 dd 的進度
    • 字串取代,使用 awk & sed
    • 尋找多種副檔名
    • 常用 VIM 選項
    • 自動 CPU 調頻節能控制
    • 自動執行程式
    • 設定 Debian 預設啟動服務
    • 設定 DHCPd server
    • 透過 RS-232 操作 Linux console
    • Linux connect to serial port
  • 資訊安全
    • ARP spoofing 技術管控區網流量實例
    • dsniff
    • Linux Socket Filtering
    • Linux 系統安全管理
    • Security 資訊
    • sniffer 相關工具 - IPgrad, tcpick
    • 以 Linux 實務 ARP Spoofing
    • 將文字隱藏於 JPEG 圖檔
    • 資安工具
    • 資安相關網站
    • 限制 localhost 的 P2P 上傳流量
  • 實用工具
    • 實驗基本數據製圖指令 gnuplot
  • 交換連結
  • 網頁設定
  • 網路應用
    • 網路時光機
  • Foldng@Home
  • 文獻推薦
    • 電子書
    • 提問的智慧
    • 好書
  • 隱私政策
Powered by GitBook
On this page
Edit on GitHub
  1. Linux 程式設計

glibc detected (double free)

PreviousGDB 參數NextIEEE 754 and float 範例程式

Last updated 2 years ago

Environment: Ubuntu 10.04 C compiler: gcc version 4.4.3 如 果 C 程式出現了下列的錯誤訊息 (glibc detected .... double free ...),依據錯誤訊息的說明,它是 glibc 預防程式對同一塊記憶體重複 free 所進行的偵測,如果想要強制執行程式以觀察執行狀況,只要在執行程式前,將環境變數 MALLOC_CHECK_ 設定為 0 就可以關閉這項檢查,ex. MALLOC_CHECK_=0 ./test (執行檔名是 test )。 寫了下列的小程式來測試,這個程式沒做什麼事情,主要只是配置了一個動態的二維記憶體空間 (10 * 32),再一一釋放記憶體,程式就結束了,這個程式就會引起 double free 的問題,在往下看結果之前,請研究這隻程式哪裡有問題?

1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 7 char **str = NULL; 8 const int x=10; 9 const int y=32; 10 int i; 11 12 str = (char**) malloc ( sizeof(char) * x ); 13 14 /* NULL pointer */ 15 if( ! str ) { 16 printf("NULL Pointer\n"); 17 return -1; 18 } 19 20 printf("Address of str=%x, and point to %x\n", &str, str); 21 22 bzero(str, x); 23 24 printf("---------------------------------------------------\n"); 25 26 for( i=0; i<x; i++) { 27 28 str[i] = (char *)malloc( sizeof(char) * y ); 29 30 if( ! str[i] ) { 31 printf("NULL Pointer\n"); 32 return -1; 33 } 34 35 36 printf("Address of str[%d]=%x, and point to %x\n", i, &str[i], str[i]); 37 38 bzero(str[i], y); 39 strcpy(str[i], "hello"); 40 41 } 42 43 44 printf("---------------------------------------------------\n"); 45 46 for( i=0; i<x; i++) { 47 48 if( str[i] ) { 49 free( str[i] ); 50 } 51 } 52 53 if(str) { 54 free (str); 55 } 56 57 return 0; 58 } 59

上面的程式執行時出現了錯誤訊息

ming@linuxbox:/tmp$ gcc test.c -o test ming@linuxbox:/tmp$ ./test Address of str=bfe0e6ec, and point to 8884008 --------------------------------------------------- Address of str[0]=8884008, and point to 8884018 Address of str[1]=888400c, and point to 8884040 Address of str[2]=8884010, and point to 8884068 Address of str[3]=8884014, and point to 8884090 Address of str[4]=8884018, and point to 88840b8 Address of str[5]=888401c, and point to 88840e0 Address of str[6]=8884020, and point to 8884108 Address of str[7]=8884024, and point to 8884130 Address of str[8]=8884028, and point to 8884158 Address of str[9]=888402c, and point to 8884180 --------------------------------------------------- *** glibc detected *** ./6: double free or corruption (out): 0x08884018 *** ======= Backtrace: ========= /lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x17b591] /lib/tls/i686/cmov/libc.so.6(+0x6cde8)[0x17cde8] /lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0x17fecd] ./6[0x8048696] /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x126bd6] ./6[0x8048451] ======= Memory map: ======== 00110000-00263000 r-xp 00000000 08:01 6685537 /lib/tls/i686/cmov/libc-2.11.1.so 00263000-00264000 ---p 00153000 08:01 6685537 /lib/tls/i686/cmov/libc-2.11.1.so 00264000-00266000 r--p 00153000 08:01 6685537 /lib/tls/i686/cmov/libc-2.11.1.so 00266000-00267000 rw-p 00155000 08:01 6685537 /lib/tls/i686/cmov/libc-2.11.1.so 00267000-0026a000 rw-p 00000000 00:00 0 003b8000-003b9000 r-xp 00000000 00:00 0 [vdso] 00ef0000-00f0d000 r-xp 00000000 08:01 6553683 /lib/libgcc_s.so.1 00f0d000-00f0e000 r--p 0001c000 08:01 6553683 /lib/libgcc_s.so.1 00f0e000-00f0f000 rw-p 0001d000 08:01 6553683 /lib/libgcc_s.so.1 00f85000-00fa0000 r-xp 00000000 08:01 6553649 /lib/ld-2.11.1.so 00fa0000-00fa1000 r--p 0001a000 08:01 6553649 /lib/ld-2.11.1.so 00fa1000-00fa2000 rw-p 0001b000 08:01 6553649 /lib/ld-2.11.1.so 08048000-08049000 r-xp 00000000 08:01 6684686 /tmp/6 08049000-0804a000 r--p 00000000 08:01 6684686 /tmp/6 0804a000-0804b000 rw-p 00001000 08:01 6684686 /tmp/6 08884000-088a5000 rw-p 00000000 00:00 0 [heap] b7700000-b7721000 rw-p 00000000 00:00 0 b7721000-b7800000 ---p 00000000 00:00 0 b7833000-b7834000 rw-p 00000000 00:00 0 b7848000-b784b000 rw-p 00000000 00:00 0 bfdfb000-bfe10000 rw-p 00000000 00:00 0 [stack] Aborted

上面的程式都有檢查所 要進行 free memory 的 pointer,正常的邏輯下不會對一個 pointer 進行兩次以上的 free,但是,將記憶體位址印出來就會發現問題,原因是在配置 pointer 的記憶體時,型態的大小配置錯誤 sizeof(char),所以其實 pointer 所指向的記憶體區塊發生了問題,產生了兩個 pointers 指向同一塊 memory 的重複情況,因此,glibc 才會偵測到有 double free 發生。

ming@linuxbox:/tmp$ gcc test.c -o test ming@linuxbox:/tmp$ MALLOC_CHECK_=0 ./test Address of str=bfabe5ac, and point to 85af008 --------------------------------------------------- Address of str[0]=85af008, and point to 85af018 Address of str[1]=85af00c, and point to 85af040 Address of str[2]=85af010, and point to 85af068 Address of str[3]=85af014, and point to 85af090 Address of str[4]=85af018, and point to 85af0b8 Address of str[5]=85af01c, and point to 85af0e0 Address of str[6]=85af020, and point to 85af108 Address of str[7]=85af024, and point to 85af130 Address of str[8]=85af028, and point to 85af158 Address of str[9]=85af02c, and point to 85af180 ---------------------------------------------------

修改程式碼第 12 行的部分,因為這塊記憶體每個 atom 的 data type 是 pointer,因此,在 malloc memory 時要注意每個 atom 的大小是配置 size of pointer,而不是 size of data type。

接著每個 str[i] 所指的記憶體每個 atom 的 data type 是 character,所以這個程式正常的配置記憶體情況將如下圖所示 (程式碼 26 ~ 41 行)

1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(int argc, char *argv[]) 5 { 6 7 char **str = NULL; 8 const int x=10; 9 const int y=32; 10 int i; 11 12 str = (char**) malloc ( sizeof(str) * x ) ; 13 14 /* NULL pointer */ 15 if( ! str ) { 16 printf("NULL Pointer\n"); 17 return -1; 18 } 19 20 printf("Address of str=%x, and point to %x\n", &str, str); 21 22 bzero(str, x); 23 24 printf("---------------------------------------------------\n"); 25 26 for( i=0; i<x; i++) { 27 28 str[i] = (char *)malloc( sizeof(char) * y ); 29 30 if( ! str[i] ) { 31 printf("NULL Pointer\n"); 32 return -1; 33 } 34 35 36 printf("Address of str[%d]=%x, and point to %x\n", i, &str[i], str[i]); 37 38 bzero(str[i], y); 39 strcpy(str[i], "hello"); 40 41 } 42 43 44 printf("---------------------------------------------------\n"); 45 46 for( i=0; i<x; i++) { 47 48 if( str[i] ) { 49 free( str[i] ); 50 } 51 } 52 53 if(str) { 54 free (str); 55 } 56 57 return 0; 58 } 59

修正後的執行結果就正確了,程式執行時也不再出現 double free 的錯誤訊息。

ming@linuxbox:/tmp$ gcc test.c -o test ming@linuxbox:/tmp$ ./test Address of str=bfaa32bc, and point to 8c5c008 --------------------------------------------------- Address of str[0]=8c5c008, and point to 8c5c038 Address of str[1]=8c5c00c, and point to 8c5c060 Address of str[2]=8c5c010, and point to 8c5c088 Address of str[3]=8c5c014, and point to 8c5c0b0 Address of str[4]=8c5c018, and point to 8c5c0d8 Address of str[5]=8c5c01c, and point to 8c5c100 Address of str[6]=8c5c020, and point to 8c5c128 Address of str[7]=8c5c024, and point to 8c5c150 Address of str[8]=8c5c028, and point to 8c5c178 Address of str[9]=8c5c02c, and point to 8c5c1a0 ---------------------------------------------------

Reference: Red Hat and Fedora Core compatibility tweaks, .

http://dag.wieers.com/howto/compatibility/