# glibc detected (double free)

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 的問題，在往下看結果之前，請研究這隻程式哪裡有問題? \\

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

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

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

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

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

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

<figure><img src="https://2908863322-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5SywTrDisUUyVAhEF6Ek%2Fuploads%2Fgit-blob-7c6beb3ff52ef0c08e57de9132aada44e0cedc76%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

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

<figure><img src="https://2908863322-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5SywTrDisUUyVAhEF6Ek%2Fuploads%2Fgit-blob-011e5614b1e7752d42bf10bf9c2248853a075708%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

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

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

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

Reference:\
Red Hat and Fedora Core compatibility tweaks, [http://dag.wieers.com/howto/compatibility/](https://web.archive.org/web/20200306075345/http://www.google.com/url?q=http%3A%2F%2Fdag.wieers.com%2Fhowto%2Fcompatibility%2F\&sa=D\&sntz=1\&usg=AFrqEzd8xJm8X87lzEwQ2iV8Xc8xYM4KRQ).
