問題現(xiàn)象描述:
使用 fopen, popen 時(shí):received signal SIGSEGV, Segmentation fault。內(nèi)部可能調(diào)用了 malloc
使用 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
- 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]
- 問題復(fù)現(xiàn)的位置可能會(huì)發(fā)生變動(dòng)。但都涉及到了內(nèi)存分配,如 fopen,
popen 的內(nèi)部實(shí)現(xiàn)調(diào)用了內(nèi)存分配函數(shù)。
調(diào)試分析:
- 檢查 fopen 的文件路徑是否存在,文件若存在,檢查文件的權(quán)限,參考【1】,已排除該可能。
- 檢查內(nèi)存誤操作:
§ 內(nèi)存重復(fù)釋放,出現(xiàn)double free時(shí),通常是由于這種情況所致。 § 內(nèi)存泄露,分配的內(nèi)存忘了釋放。 § 內(nèi)存越界使用,使用了不該使用的內(nèi)存。 § 使用了無效指針。 § 空指針,對(duì)一個(gè)空指針進(jìn)行操作。
- 像是 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的位置掛住。
解決方案:
先通過日志定位問題的大致位置(可用valgrind作輔助分析,參考【7】)。使用排除法分析,排除不可能出錯(cuò)的步驟,然后gdb進(jìn)入線程單步調(diào)試,gdb 參考【9】。
發(fā)現(xiàn) delete 一塊內(nèi)存的時(shí)候掛起,而這塊內(nèi)存在其他線程中使用,內(nèi)
存指向的結(jié)構(gòu)體中還有包含其他分配內(nèi)存的指針。這就是問題的所在。
所以,將刪除內(nèi)存的操作放在 if 條件判斷中,只刪除其他線程不使用的
內(nèi)存。單步調(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.