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

| <p>  1 #include \<stdio.h><br>  2 #include \<stdlib.h><br>  3<br>  4 int main(int argc, char *argv\[])<br>  5 {<br>  6<br>  7         char **str = NULL;<br>  8         const int x=10;<br>  9         const int y=32;<br> 10         int i;<br> 11<br> 12         str = (char**) malloc ( sizeof(char) \* x );<br> 13<br> 14         /* 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> |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

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

| <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**。<br>

<figure><img src="/files/ZvSpa5Z0dTHHsOzYb1Ww" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/rsR0AENCWszQE1DOBTcA" alt=""><figcaption></figcaption></figure>

| <p>  1 #include \<stdio.h><br>  2 #include \<stdlib.h><br>  3<br>  4 int main(int argc, char *argv\[])<br>  5 {<br>  6<br>  7         char **str = NULL;<br>  8         const int x=10;<br>  9         const int y=32;<br> 10         int i;<br> 11<br> 12         str = (char**) malloc ( sizeof(str) \* x ) ;<br> 13<br> 14         /* 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 的錯誤訊息。<br>

| <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).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://applezulab.netdpi.net/linux-prog/glibc-detected-double-free.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
