01 - fopen、popen 引起 Segmentation fault

問題現(xiàn)象描述:

  1. 使用 fopen, popen 時(shí):received signal SIGSEGV, Segmentation fault。內(nèi)部可能調(diào)用了 malloc

  2. 使用 fopen 時(shí):(fopen Segmentation fault)

Thread 1 "./***_app" received signal SIGSEGV, Segmentation fault.  
_int_malloc (av=av@entry=0x7ffff71a0b20 <main_arena>,  
bytes=bytes@entry=552) at malloc.c:3516
3516      malloc.c: No such file or directory.
(gdb) bt
  #0  _int_malloc (av=av@entry=0x7ffff71a0b20 <main_arena>, bytes=bytes@entry=552) at malloc.c:3516
  #1  0x00007ffff6e60184 in __GI___libc_malloc (bytes=552) at malloc.c:2913
  #2  0x00007ffff6e49cdd in __fopen_internal (filename=0x6990f0 "./conf/moniter.conf", mode=0x467374 "r", is32=1) at iofopen.c:69  
  1. memory corruption:
  *** Error in `./***_app': malloc(): memory corruption: >0x0000000001bac6c0 ***
  ======= Backtrace: =========
  /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f4c4e6be7e5]
  /lib/x86_64-linux-gnu/libc.so.6(+0x8213e)[0x7f4c4e6c913e]
  /lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7f4c4e6cb184]
  /lib/x86_64-linux-gnu/libc.so.6(+0x6dcdd)[0x7f4c4e6b4cdd]
  ./***_app[0x4269d3]
  ./***_app[0x428e79]
  ./***_app[0x42c386]
  /lib/x86_64-linux-gnu/libc.so.6(+0x354b0)[0x7f4c4e67c4b0]
  /lib/x86_64-linux-gnu/libc.so.6(nanosleep+0x2d)[0x7f4c4e71330d]
  /lib/x86_64-linux-gnu/libc.so.6(sleep+0x2a)[0x7f4c4e71325a]
  ./***_app[0x406106]
  /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f4c4e667830]
  ./***_app[0x4056c9]
  ======= Memory map: ========  
   00400000-00497000 r-xp 00000000 08:02 37464  
   /root/working/.../.../.../.../***_app
   00697000-00698000 r--p 00097000 08:02 37464                         
   /root/working/.../.../.../.../***_app
   00698000-00699000 rw-p 00098000 08:02 37464   
   /root/working/.../.../.../.../***_app 
   00699000-0069a000 rw-p 00000000 00:00 0   
   01b7a000-01bec000 rw-p 00000000 00:00 0                                   
   [heap]  
  1. 問題復(fù)現(xiàn)的位置可能會(huì)發(fā)生變動(dòng)。但都涉及到了內(nèi)存分配,如 fopen,
    popen 的內(nèi)部實(shí)現(xiàn)調(diào)用了內(nèi)存分配函數(shù)。

調(diào)試分析:

  1. 檢查 fopen 的文件路徑是否存在,文件若存在,檢查文件的權(quán)限,參考【1】,已排除該可能。
  2. 檢查內(nèi)存誤操作:
§ 內(nèi)存重復(fù)釋放,出現(xiàn)double free時(shí),通常是由于這種情況所致。
§ 內(nèi)存泄露,分配的內(nèi)存忘了釋放。
§ 內(nèi)存越界使用,使用了不該使用的內(nèi)存。
§ 使用了無效指針。
§ 空指針,對(duì)一個(gè)空指針進(jìn)行操作。 
  1. 像是 fopen,popen 或者是其他內(nèi)部含有 malloc 等內(nèi)存分配函數(shù)的函數(shù),導(dǎo)致 Segmentation fault,或者是 malloc memory corruption,一般問題都不在 fopen ,和 popen 本身。而在與在他們之前(時(shí)間或空間)的操作,對(duì)內(nèi)存作了以上5種誤操作中的一種。導(dǎo)致破壞了堆中的內(nèi)存分配信息數(shù)據(jù),特別是動(dòng)態(tài)分配的內(nèi)存塊的內(nèi)存信息 數(shù)據(jù),因?yàn)椴僮飨到y(tǒng)在分配和釋放內(nèi)存塊時(shí)需要訪問該數(shù)據(jù)。這里請(qǐng)重點(diǎn)參看:【6】 其作者的分析可謂十分到位,一針見血,看了猶如醍醐灌頂。

問題原因:

多線程中某一動(dòng)態(tài)分配的對(duì)象同時(shí)被兩個(gè)線程使用,管理線程釋放對(duì)象
時(shí),理應(yīng)判斷該對(duì)象是否在而另一工作線程中有效。而我卻在管理線程
中,把對(duì)該對(duì)象的釋放操作,放在了判斷語句的外面,導(dǎo)致執(zhí)行了刪除
正在使用的對(duì)象的操作,gdb調(diào)試中,在delete的位置掛住。

解決方案:

  1. 先通過日志定位問題的大致位置(可用valgrind作輔助分析,參考【7】)。使用排除法分析,排除不可能出錯(cuò)的步驟,然后gdb進(jìn)入線程單步調(diào)試,gdb 參考【9】。

  2. 發(fā)現(xiàn) delete 一塊內(nèi)存的時(shí)候掛起,而這塊內(nèi)存在其他線程中使用,內(nèi)
    存指向的結(jié)構(gòu)體中還有包含其他分配內(nèi)存的指針。這就是問題的所在。
    所以,將刪除內(nèi)存的操作放在 if 條件判斷中,只刪除其他線程不使用的
    內(nèi)存。

  3. 單步調(diào)試雖然累,但是一點(diǎn)要耐心,理清自己的代碼邏輯,特別是要
    留意gdb的backtrace和valgrind的報(bào)錯(cuò)信息,這會(huì)讓你排除大部分無關(guān)
    項(xiàng),直搗黃龍附近。

參考文章:

[0]. https://blog.csdn.net/slvher/article/details/9144161
[1]. https://www.cnblogs.com/YuNanlong/p/8896429.html
[2]. http://www.lazylab.org/204/linux/glibc-detected-malloc-memory-corruption-0x0916c100-error/
[3]. https://blog.csdn.net/tommy_lgj/article/details/2790452
[4]. https://blog.csdn.net/icycode/article/details/49645725
[5]. https://blog.csdn.net/XuLujunCSDN/article/details/71191550
[6]. https://blog.csdn.net/wangyunqian6/article/details/48931835
[7]. https://blog.csdn.net/miss_acha/article/details/19839715
[8]. https://www.oschina.net/translate/valgrind-is-not-a-leak-checker
[9]. https://blog.csdn.net/weiyuefei/article/details/52374285

參考樣張

【2】

***glibc detected*** malloc(): memory corruption: 0x0916c100 *** error     
Memory corruption error comes when you are doing something on memory which is not available.
Like Writing,Reading and freeing.
Some common examples are
        ○ Reading/writing to memory out of the bounds of a dynamically allocated array
        ○ Attempting to write a memory which was never allocated
        ○ Attempting to free a memory already freed
        ○ Writing to a freed memory
        ○ Writing to an unallocated memory
Fix:
        ○ Check the above common mistakes
        ○ Check all malloc() expressions in your code
        ○ Check if data is copied to an allocated memory whose allocated length is less than data(ex. in memcpy() statements)
        ○ This error usually comes while allocating memory to arrays like
            pointer = (char *) malloc(strlen(Array_B));
        the above statement overflows by 1 byte. You should use-
            pointer = (char *) malloc(strlen(Array_B)+1);
        to avoid any memory corruptions.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容