Linux下SegmentFault(double free)分析方法(一)Gdb

Linux下SegmentFault(double free)分析方法(一)Gdb

一、Gdb基本用法

gdb的基本用法可以查看具体的man手册,

man gdb 

或者gdb官网查看
,本文不介绍器详细的用法,只是简单用一下。 GDB官网文档 http://www.gnu.org/software/gdb/documentation/
可以去官网下载gdb的文档

二、示例代码

double_free_main.cpp

#include <vector>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <stdio.h>
#include <unistd.h>
#pragma  pack(1)
typedef struct Test
{
    int s32_test;
    unsigned char u8_test;
    unsigned int u32_test;
    unsigned short u16_test;
    std::vector <unsigned char> vec_data;
    float f_test;
    double d_test;
    unsigned long long u64_test;
}Test;
#pragma  pack(0)
void MyCopy(Test * pst_dst,const Test * pst_src)
{
    if(pst_src == NULL || pst_dst == NULL)
    {
        printf("%s(%d)pst_src %p  pst_dst %p \n",__FUNCTION__,__LINE__,pst_src,pst_dst);
    }
    else
    {
        printf("%s(%d)  sizeof(Test) %d\n",__FUNCTION__,__LINE__,sizeof(Test));
        memcpy(pst_dst,pst_src,sizeof(Test)); //有问题代码
        //*pst_dst = *pst_src;//正确使用方法
    }
    
}

int  MyTest(void)
{
    Test st_test1,st_test2;
    st_test1.s32_test = -15;
    st_test1.u8_test = 255;
    st_test1.u16_test = 65535;
    st_test1.u32_test = 123456789;
    st_test1.vec_data.resize(512);
    st_test1.vec_data[0] = 100;
    st_test1.vec_data[50] = 100;
    st_test1.f_test = 5.6;
    st_test1.d_test = 10.236589;
    st_test1.u64_test = 15666;
    MyCopy(&st_test2,&st_test1);
    return 0;
}


void MyTest2(void)
{
    std::vector <unsigned char> vec_test1,vec_test2;
    vec_test1.push_back(1);
    vec_test1.push_back(2);
    vec_test1.push_back(3);
    vec_test2.resize(vec_test1.size());
    memcpy(&vec_test2,&vec_test1,vec_test1.size());//有问题代码
    //vec_test2 = vec_test1;//正确使用
}


int main(void)
{
   MyTest2();
   printf("%s(%d)  sizeof(Test) %d\n",__FUNCTION__,__LINE__,sizeof(Test));
   MyTest();
   while(1)
   {
       printf("%s(%d)  sizeof(Test) %d\n",__FUNCTION__,__LINE__,sizeof(Test));
   }
   return 0;
}

三、编译调试代码

利用g++ 进行编译时一定要加上 -g 选项

root@ubuntu:/FlyInCoding/c++/vs/double_free# g++ -g -o double_free_main double_free_main.cpp
root@ubuntu:/FlyInCoding/c++/vs/double_free# gdb double_free_main
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from double_free_main...done.
(gdb) r
Starting program: /DFlyInCoding/c++/vs/double_free/double_free_main 
*** Error in 
`/FlyInCoding/c++/vs/double_free/double_free_main': double free or corruption (fasttop): 0x08052a10 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67377)[0xb7ce1377]
/lib/i386-linux-gnu/libc.so.6(+0x6d2f7)[0xb7ce72f7]
/lib/i386-linux-gnu/libc.so.6(+0x6dc31)[0xb7ce7c31]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x18)[0xb7ebbd88]
/FlyInCoding/c++/vs/double_free/double_free_main[0x80496c7]
/FlyInCoding/c++/vs/double_free/double_free_main[0x80491bd]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8049329]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8048f34]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8048b0c]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8048b48]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xb7c92637]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8048801]
======= Memory map: ========
08048000-0804c000 r-xp 00000000 08:01 1196883    /FlyInCoding/c++/vs/double_free/double_free_main
0804c000-0804d000 r--p 00003000 08:01 1196883    /FlyInCoding/c++/vs/double_free/double_free_main
0804d000-0804e000 rw-p 00004000 08:01 1196883    /FlyInCoding/c++/vs/double_free/double_free_main
0804e000-08073000 rw-p 00000000 00:00 0          [heap]
b7b00000-b7b21000 rw-p 00000000 00:00 0 
b7b21000-b7c00000 ---p 00000000 00:00 0 
b7c22000-b7c25000 rw-p 00000000 00:00 0 
b7c25000-b7c78000 r-xp 00000000 08:01 1578873    /lib/i386-linux-gnu/libm-2.23.so
b7c78000-b7c79000 r--p 00052000 08:01 1578873    /lib/i386-linux-gnu/libm-2.23.so
b7c79000-b7c7a000 rw-p 00053000 08:01 1578873    /lib/i386-linux-gnu/libm-2.23.so
b7c7a000-b7e2a000 r-xp 00000000 08:01 1578877    /lib/i386-linux-gnu/libc-2.23.so
b7e2a000-b7e2c000 r--p 001af000 08:01 1578877    /lib/i386-linux-gnu/libc-2.23.so
b7e2c000-b7e2d000 rw-p 001b1000 08:01 1578877    /lib/i386-linux-gnu/libc-2.23.so
b7e2d000-b7e30000 rw-p 00000000 00:00 0 
b7e30000-b7e4c000 r-xp 00000000 08:01 1572917    /lib/i386-linux-gnu/libgcc_s.so.1
b7e4c000-b7e4d000 rw-p 0001b000 08:01 1572917    /lib/i386-linux-gnu/libgcc_s.so.1
b7e4d000-b7fba000 r-xp 00000000 08:01 665354     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7fba000-b7fbb000 ---p 0016d000 08:01 665354     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7fbb000-b7fc0000 r--p 0016d000 08:01 665354     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7fc0000-b7fc1000 rw-p 00172000 08:01 665354     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7fc1000-b7fc4000 rw-p 00000000 00:00 0 
b7fd6000-b7fd8000 rw-p 00000000 00:00 0 
b7fd8000-b7fda000 r--p 00000000 00:00 0          [vvar]
b7fda000-b7fdb000 r-xp 00000000 00:00 0          [vdso]
b7fdb000-b7ffe000 r-xp 00000000 08:01 1578875    /lib/i386-linux-gnu/ld-2.23.so
b7ffe000-b7fff000 r--p 00022000 08:01 1578875    /lib/i386-linux-gnu/ld-2.23.so
b7fff000-b8000000 rw-p 00023000 08:01 1578875    /lib/i386-linux-gnu/ld-2.23.so
bffdf000-c0000000 rw-p 00000000 00:00 0          [stack]

Program received signal SIGABRT, Aborted.
0xb7fdac31 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fdac31 in __kernel_vsyscall ()
#1  0xb7ca5ea9 in __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#2  0xb7ca7407 in __GI_abort () at abort.c:89
#3  0xb7ce137c in __libc_message (do_abort=2, fmt=0xb7dd9e54 "*** Error in `%s': %s: 0x%s ***\n")
    at ../sysdeps/posix/libc_fatal.c:175
#4  0xb7ce72f7 in malloc_printerr (action=<optimized out>, str=0xb7dd9f94 "double free or corruption (fasttop)", 
    ptr=<optimized out>, ar_ptr=0xb7e2c780 <main_arena>) at malloc.c:5006
#5  0xb7ce7c31 in _int_free (av=0xb7e2c780 <main_arena>, p=<optimized out>, have_lock=0) at malloc.c:3867
#6  0xb7ebbd88 in operator delete(void*) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#7  0x080496c7 in __gnu_cxx::new_allocator<unsigned char>::deallocate (this=0xbffff498, __p=0x8052a10 "")
    at /usr/include/c++/4.8/ext/new_allocator.h:110
#8  0x080491bd in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_deallocate (this=0xbffff498, 
    __p=0x8052a10 "", __n=4) at /usr/include/c++/4.8/bits/stl_vector.h:174
#9  0x08049329 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::~_Vector_base (this=0xbffff498, 
    __in_chrg=<optimized out>) at /usr/include/c++/4.8/bits/stl_vector.h:160
#10 0x08048f34 in std::vector<unsigned char, std::allocator<unsigned char> >::~vector (this=0xbffff498, __in_chrg=<optimized out>)
    at /usr/include/c++/4.8/bits/stl_vector.h:416
#11 0x08048b0c in MyTest2 () at double_free_main.cpp:61
#12 0x08048b48 in main () at double_free_main.cpp:67
(gdb) f 11
#11 0x08048b0c in MyTest2 () at double_free_main.cpp:61
61          memcpy(&vec_test2,&vec_test1,vec_test1.size());
(gdb) p vec_test2
$1 = std::vector of length 19, capacity 19 = {0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 17 '\021', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000'}
(gdb) p vec_test1
$2 = std::vector of length 3, capacity 4 = {0 '\000', 0 '\000', 0 '\000'}
(gdb) b MyTest2
Breakpoint 1 at 0x8048a5b: file double_free_main.cpp, line 56.
(gdb) c
Continuing.

Program terminated with signal SIGABRT, Aborted.
The program no longer exists.
(gdb) r
Starting program: /FlyInCoding/c++/vs/double_free/double_free_main 

Breakpoint 1, MyTest2 () at double_free_main.cpp:56
56          std::vector <unsigned char> vec_test1,vec_test2;
(gdb) n
57          vec_test1.push_back(1);
(gdb) 
58          vec_test1.push_back(2);
(gdb) 
59          vec_test1.push_back(3);
(gdb) 
60          vec_test2.resize(vec_test1.size());
(gdb) 
61          memcpy(&vec_test2,&vec_test1,vec_test1.size());
(gdb) p vec_test2
$3 = std::vector of length 3, capacity 3 = {0 '\000', 0 '\000', 0 '\000'}
(gdb) p vec_test1
$4 = std::vector of length 3, capacity 4 = {1 '\001', 2 '\002', 3 '\003'}
(gdb) n
56          std::vector <unsigned char> vec_test1,vec_test2;
(gdb) p vec_test2
$5 = std::vector of length 19, capacity 19 = {1 '\001', 2 '\002', 3 '\003', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 
  0 '\000', 0 '\000', 0 '\000', 0 '\000', 17 '\021', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000', 0 '\000'}
(gdb) p vec_test1
$6 = std::vector of length 3, capacity 4 = {1 '\001', 2 '\002', 3 '\003'}
(gdb) n
61          memcpy(&vec_test2,&vec_test1,vec_test1.size());
(gdb) n
*** Error in `
/FlyInCoding/c++/vs/double_free/double_free_main': double free or corruption (fasttop): 0x08052a10 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x67377)[0xb7ce1377]
/lib/i386-linux-gnu/libc.so.6(+0x6d2f7)[0xb7ce72f7]
/lib/i386-linux-gnu/libc.so.6(+0x6dc31)[0xb7ce7c31]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x18)[0xb7ebbd88]
/FlyInCoding/c++/vs/double_free/double_free_main[0x80496c7]
/FlyInCoding/c++/vs/double_free/double_free_main[0x80491bd]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8049329]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8048f34]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8048b0c]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8048b48]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf7)[0xb7c92637]
/FlyInCoding/c++/vs/double_free/double_free_main[0x8048801]
======= Memory map: ========
08048000-0804c000 r-xp 00000000 08:01 1196883    /FlyInCoding/c++/vs/double_free/double_free_main
0804c000-0804d000 r--p 00003000 08:01 1196883    /FlyInCoding/c++/vs/double_free/double_free_main
0804d000-0804e000 rw-p 00004000 08:01 1196883    /FlyInCoding/c++/vs/double_free/double_free_main
0804e000-08073000 rw-p 00000000 00:00 0          [heap]
b7b00000-b7b21000 rw-p 00000000 00:00 0 
b7b21000-b7c00000 ---p 00000000 00:00 0 
b7c22000-b7c25000 rw-p 00000000 00:00 0 
b7c25000-b7c78000 r-xp 00000000 08:01 1578873    /lib/i386-linux-gnu/libm-2.23.so
b7c78000-b7c79000 r--p 00052000 08:01 1578873    /lib/i386-linux-gnu/libm-2.23.so
b7c79000-b7c7a000 rw-p 00053000 08:01 1578873    /lib/i386-linux-gnu/libm-2.23.so
b7c7a000-b7e2a000 r-xp 00000000 08:01 1578877    /lib/i386-linux-gnu/libc-2.23.so
b7e2a000-b7e2c000 r--p 001af000 08:01 1578877    /lib/i386-linux-gnu/libc-2.23.so
b7e2c000-b7e2d000 rw-p 001b1000 08:01 1578877    /lib/i386-linux-gnu/libc-2.23.so
b7e2d000-b7e30000 rw-p 00000000 00:00 0 
b7e30000-b7e4c000 r-xp 00000000 08:01 1572917    /lib/i386-linux-gnu/libgcc_s.so.1
b7e4c000-b7e4d000 rw-p 0001b000 08:01 1572917    /lib/i386-linux-gnu/libgcc_s.so.1
b7e4d000-b7fba000 r-xp 00000000 08:01 665354     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7fba000-b7fbb000 ---p 0016d000 08:01 665354     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7fbb000-b7fc0000 r--p 0016d000 08:01 665354     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7fc0000-b7fc1000 rw-p 00172000 08:01 665354     /usr/lib/i386-linux-gnu/libstdc++.so.6.0.21
b7fc1000-b7fc4000 rw-p 00000000 00:00 0 
b7fd6000-b7fd8000 rw-p 00000000 00:00 0 
b7fd8000-b7fda000 r--p 00000000 00:00 0          [vvar]
b7fda000-b7fdb000 r-xp 00000000 00:00 0          [vdso]
b7fdb000-b7ffe000 r-xp 00000000 08:01 1578875    /lib/i386-linux-gnu/ld-2.23.so
b7ffe000-b7fff000 r--p 00022000 08:01 1578875    /lib/i386-linux-gnu/ld-2.23.so
b7fff000-b8000000 rw-p 00023000 08:01 1578875    /lib/i386-linux-gnu/ld-2.23.so
bffdf000-c0000000 rw-p 00000000 00:00 0          [stack]

Program received signal SIGABRT, Aborted.
0xb7fdac31 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fdac31 in __kernel_vsyscall ()
#1  0xb7ca5ea9 in __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#2  0xb7ca7407 in __GI_abort () at abort.c:89
#3  0xb7ce137c in __libc_message (do_abort=2, fmt=0xb7dd9e54 "*** Error in `%s': %s: 0x%s ***\n")
    at ../sysdeps/posix/libc_fatal.c:175
#4  0xb7ce72f7 in malloc_printerr (action=<optimized out>, str=0xb7dd9f94 "double free or corruption (fasttop)", 
    ptr=<optimized out>, ar_ptr=0xb7e2c780 <main_arena>) at malloc.c:5006
#5  0xb7ce7c31 in _int_free (av=0xb7e2c780 <main_arena>, p=<optimized out>, have_lock=0) at malloc.c:3867
#6  0xb7ebbd88 in operator delete(void*) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#7  0x080496c7 in __gnu_cxx::new_allocator<unsigned char>::deallocate (this=0xbffff498, __p=0x8052a10 "")
    at /usr/include/c++/4.8/ext/new_allocator.h:110
#8  0x080491bd in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_deallocate (this=0xbffff498, 
    __p=0x8052a10 "", __n=4) at /usr/include/c++/4.8/bits/stl_vector.h:174
#9  0x08049329 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::~_Vector_base (this=0xbffff498, 
    __in_chrg=<optimized out>) at /usr/include/c++/4.8/bits/stl_vector.h:160
#10 0x08048f34 in std::vector<unsigned char, std::allocator<unsigned char> >::~vector (this=0xbffff498, __in_chrg=<optimized out>)
    at /usr/include/c++/4.8/bits/stl_vector.h:416
#11 0x08048b0c in MyTest2 () at double_free_main.cpp:61
#12 0x08048b48 in main () at double_free_main.cpp:67
(gdb) 

通过查看出问题时的堆栈信息基本上可以定位到是函数memcpy时出现的问题。至于为什么出现该问题,那就是c++ 有关深拷贝和浅拷贝的问题,不是本文的讨论范围,今后会在其他博文中讨论该问题,上述代码正确的写法已经在注释中表明。

发布了67 篇原创文章 · 获赞 15 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/wanxuexiang/article/details/88101061