linux下GDB是一个非常强大的调试工具,但是他不像vs一样具有强大的图形界面,基本都靠命令来进行调试,对于新手来说也算是个坎。下面就跟大家一起探究一下gdb这个强大的调试工具。1.开启core1.1 查看core是否开启$ulimit -c0  0:表示关闭,不会生成core文件;否则此值说明core文件的最大限制;1.2 打开开启core  打开/etc/profile$sudo gedit /etc/profile  在文件末尾加上:ulimit -S -c unlimited > /dev/null 2>&1  wq!保存退出。然后让设置立即生效:$source /etc/profile  然后输入命令:$ulimit -cunlimited  core文件已经开启。unlimited为不限制core文件大小。1.3 设置保存core文件的路径和命名方式$sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t  /tmp目录为core文件的保存路径,core文件命名格式为:%%:相当于%%p:相当于<pid>%u:相当于<uid>%g:相当于<gid>%s:相当于导致dump的信号的数字%t:相当于dump的时间%e:相当于执行文件的名称%h:相当于hostname2.编译2.1 先准备一份简单的源码:#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include<pthread.h>void printinfo(const char* pstr){ printf("%s\n", pstr);}void* threadproc1(void* arg){ int i = 0; while(i < 20)// { printf(“I am threadproc1, tid:%u, i:%d\n”, pthread_self(), i++); sleep(1); } return NULL;}void* threadproc2(void* arg){ int i = 0; while(i < 20)// { printf(“I am threadproc2, tid:%u, i:%d\n”, pthread_self(), i++); sleep(1); } return NULL;}int main(int narg, const char** args){ const char* pstr = args[1]; printinfo(pstr); pthread_t tid1,tid2; pthread_create(&tid1,NULL,threadproc1,NULL);//创建线程1 pthread_create(&tid2,NULL,threadproc2,NULL);//创建线程2 pthread_join(tid1,NULL);//等待线程1 printf(“thread1 joined\n”); pthread_join(tid2,NULL);//等待线程2 printf(“thread2 joined\n”); free((void*)pstr); char* pend = “main end\n”; printf(pend); free(pend); return 0;}2.2 编译源码  将主程序命名为gdbtest.cpp,使用g++进行编译:$g++ -g -c gdbtest.cpp$g++ -o gdbtest gdbtest.o -lpthread  注意,编译时需要添加-g选项,通知编译器生成gdb调试信息。代码编译完成后,将在当前目录下生成gdbtest可执行程序。3 gdb调试3.1 gdb调试常用命令说明  1.gdb $(filename)  启动gdb调试,$(filename)也可以使用file命令指定;  2.file $(filename)  设置gdb调试的文件名  3. set args $(arg1) $(arg2) $(arg3) …  设置main函数输入参数  4.b/break linenum  设置断点,linenum为行号  5.r/run $(arg1) $(arg2) $(arg3) …  开始运行gdb调试,参数如果没有或者已经设置,可以不输入  6.p/print $(var)  打印变量  7.display $(var)  显示变量  8.n/next  单步执行  9.bt  显示栈帧以及局部变量  10.s/step  进入子函数  11.up  退出当前函数,返回上一级堆栈  12.c/continue  继续执行  13.list  输出从上次调用list命令开始往后的10行程序代码  14.info threads  线程信息  15.thread id  切换调试线程  16.tbreak/tb  设置临时断点,只生效一次。  16.info break/i b  显示所有断点信息3.2 gdb调试  使用GDB运行gdbtest$gdb gdbtest  在37(const char* pstr = args[1];)行设置断点(gdb)b 37Breakpoint 1 at 0x40090c: file gdbtest.cpp, line 37.  gdb调试运行,“hello, welcome to gdb debug world!“为运行参数(gdb) run “hello, welcome to gdb debug world!“Starting program: /home/zwu/Desktop/work/coding/transcode/gdbtest/gdbtest “hello, welcome to gdb debug world!"[Thread debugging using libthread_db enabled]Using host libthread_db library “/lib/x86_64-linux-gnu/libthread_db.so.1”.Breakpoint 1, main (narg=2, args=0x7fffffffdf08) at gdbtest.cpp:3737 const char* pstr = args[1];  程序运行后,停止在37行断点处。  p/print:打印args[0]变量:(gdb) p args[0]$3 = 0x7fffffffe278 “/home/zwu/Desktop/work/coding/transcode/gdbtest/gdbtest”  display:打印变量(gdb) display args[1]1: args[1] = 0x7fffffffe2b0 “hello, welcome to gdb debug world!”  n/next:执行单步调试(gdb) n38 printinfo(pstr);  s/step:进入子函数(gdb) sprintinfo (pstr=0x7fffffffe2b0 “hello, welcome to gdb debug world!")at gdbtest.cpp:99 printf(pstr);  up:退出当前函数,返回上一级堆栈:(gdb) up#1 0x0000000000400924 in main (narg=2, args=0x7fffffffdf08) at gdbtest.cpp:3838 printinfo(pstr);(gdb) nmain (narg=2, args=0x7fffffffdf08) at gdbtest.cpp:4141 pthread_create(&tid1,NULL,threadproc1,NULL);//创建线程11: args[1] = 0x7fffffffe2b0 “hello, welcome to gdb debug world!”  list:输出从上次调用list命令开始往后的10行程序代码(gdb) list36 {37 const char* pstr = args[1];38 printinfo(pstr);39 40 pthread_t tid1,tid2;41 pthread_create(&tid1,NULL,threadproc1,NULL);//创建线程142 pthread_create(&tid2,NULL,threadproc2,NULL);//创建线程243 pthread_join(tid1,NULL);//等待线程144 printf(“thread1 joined\n”);45 pthread_join(tid2,NULL);//等待线程2  输出线程信息:(gdb) info threadsId Target Id Frame * 1 Thread 0x7ffff7fdd700 (LWP 5045) “gdbtest” main (narg=2, args=0x7fffffffdf08) at gdbtest.cpp:422 Thread 0x7ffff77ef700 (LWP 5047) “gdbtest” clone ()at ../sysdeps/unix/sysv/linux/x86_64/clone.S:81  bt full输出调用栈信息(gdb) bt full0 main (narg=2, args=0x7fffffffdf08) at gdbtest.cpp:42 pstr = 0x7fffffffe2b0 “hello, welcome to gdb debug world!” tid1 = 140737345681152 tid2 = 4196832 pend = 0x7fffffffdf00 “\002”  c/continue:继续执行(gdb) cContinuing.[New Thread 0x7ffff77ef700 (LWP 4517)]hello, welcome to gdb debug world!I am threadproc1, tid:4152293120, i:0[New Thread 0x7ffff6fee700 (LWP 4518)]I am threadproc2, tid:4143900416, i:0…I am threadproc1, tid:4152293120, i:19I am threadproc2, tid:4143900416, i:19[Thread 0x7ffff6fee700 (LWP 4518) exited]thread1 joinedthread2 joined  程序在50行free(pend)时崩溃,以下为core dump信息:*** Error in /home/zwu/Desktop/work/coding/transcode/gdbtest/gdbtest': munmap_chunk(): invalid pointer: 0x00007fffffffe2b0 ***[Thread 0x7ffff77ef700 (LWP 4517) exited]======= Backtrace: =========/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7ffff78677e5]/lib/x86_64-linux-gnu/libc.so.6(cfree+0x1a8)[0x7ffff7874698]/home/zwu/Desktop/work/coding/transcode/gdbtest/gdbtest[0x40099c]/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7ffff7810830]/home/zwu/Desktop/work/coding/transcode/gdbtest/gdbtest[0x400759]======= Memory map: ========00400000-00401000 r-xp 00000000 08:01 950010 /home/zwu/Desktop/work/coding/transcode/gdbtest/gdbtest00600000-00601000 r--p 00000000 08:01 950010 /home/zwu/Desktop/work/coding/transcode/gdbtest/gdbtest00601000-00602000 rw-p 00001000 08:01 950010 /home/zwu/Desktop/work/coding/transcode/gdbtest/gdbtest00602000-00623000 rw-p 00000000 00:00 0 [heap]7ffff65d8000-7ffff65ee000 r-xp 00000000 08:01 1054507 /lib/x86_64-linux-gnu/libgcc_s.so.17ffff65ee000-7ffff67ed000 ---p 00016000 08:01 1054507 /lib/x86_64-linux-gnu/libgcc_s.so.17ffff67ed000-7ffff67ee000 rw-p 00015000 08:01 1054507 /lib/x86_64-linux-gnu/libgcc_s.so.17ffff67ee000-7ffff67ef000 ---p 00000000 00:00 0 7ffff67ef000-7ffff6fef000 rw-p 00000000 00:00 0 7ffff6fef000-7ffff6ff0000 ---p 00000000 00:00 0 7ffff6ff0000-7ffff77f0000 rw-p 00000000 00:00 0 7ffff77f0000-7ffff79b0000 r-xp 00000000 08:01 1054469 /lib/x86_64-linux-gnu/libc-2.23.so7ffff79b0000-7ffff7bb0000 ---p 001c0000 08:01 1054469 /lib/x86_64-linux-gnu/libc-2.23.so7ffff7bb0000-7ffff7bb4000 r--p 001c0000 08:01 1054469 /lib/x86_64-linux-gnu/libc-2.23.so7ffff7bb4000-7ffff7bb6000 rw-p 001c4000 08:01 1054469 /lib/x86_64-linux-gnu/libc-2.23.so7ffff7bb6000-7ffff7bba000 rw-p 00000000 00:00 0 7ffff7bba000-7ffff7bd2000 r-xp 00000000 08:01 1054615 /lib/x86_64-linux-gnu/libpthread-2.23.so7ffff7bd2000-7ffff7dd1000 ---p 00018000 08:01 1054615 /lib/x86_64-linux-gnu/libpthread-2.23.so7ffff7dd1000-7ffff7dd2000 r--p 00017000 08:01 1054615 /lib/x86_64-linux-gnu/libpthread-2.23.so7ffff7dd2000-7ffff7dd3000 rw-p 00018000 08:01 1054615 /lib/x86_64-linux-gnu/libpthread-2.23.so7ffff7dd3000-7ffff7dd7000 rw-p 00000000 00:00 0 7ffff7dd7000-7ffff7dfd000 r-xp 00000000 08:01 1054441 /lib/x86_64-linux-gnu/ld-2.23.so7ffff7fdc000-7ffff7fe0000 rw-p 00000000 00:00 0 7ffff7ff6000-7ffff7ff7000 rw-p 00000000 00:00 0 7ffff7ff7000-7ffff7ffa000 r--p 00000000 00:00 0 [vvar]7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso]7ffff7ffc000-7ffff7ffd000 r--p 00025000 08:01 1054441 /lib/x86_64-linux-gnu/ld-2.23.so7ffff7ffd000-7ffff7ffe000 rw-p 00026000 08:01 1054441 /lib/x86_64-linux-gnu/ld-2.23.so7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0 7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]Thread 1 "gdbtest" received signal SIGABRT, Aborted.0x00007ffff7825428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:5454 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.  注:gdb调试时,遇到coredump将直接输出coredump信息,不会生成core文件。4.coredump文件调试  退出gdb,在terminal中直接运行:$./gdbtest*** Error in ./gdbtest’: free(): invalid pointer: 0x0000000000400ac6 **======= Backtrace: =========/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f83f713e7e5]/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f83f714737a]/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f83f714b53c]./gdbtest[0x4009c1]/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f83f70e7830]./gdbtest[0x400759]  程序崩溃,并在/tmp目录下产生core-gdbtest..ubuntu.的core dump文件,如果想要解析该文件,只需输入gdb $(program) $(coredump)$gdb gdbtest core-gdbtest..ubuntu.*GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1Copyright (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 “x86_64-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 gdbtest…done.[New LWP 5183][Thread debugging using libthread_db enabled]Using host libthread_db library “/lib/x86_64-linux-gnu/libthread_db.so.1”.Core was generated by ./gdbtest'.Program terminated with signal SIGABRT, Aborted.#0 0x00007f83f70fc428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54 54 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.  输入bt,查看崩溃程序的调用栈(gdb) bt#0 0x00007f83f70fc428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54#1 0x00007f83f70fe02a in __GI_abort () at abort.c:89#2 0x00007f83f713e7ea in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7f83f7257ed8 "*** Error in %s’: %s: 0x%s ***\n”) at ../sysdeps/posix/libc_fatal.c:175#3 0x00007f83f714737a in malloc_printerr (ar_ptr=<optimized out>, ptr=<optimized out>, str=0x7f83f7254caf “free(): invalid pointer”, action=3) at malloc.c:5006#4 _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3867#5 0x00007f83f714b53c in __GI___libc_free (mem=<optimized out>) at malloc.c:2968#6 0x00000000004009c1 in main (narg=1, args=0x7fff510a3d48) at gdbtest.cpp:50  在没有调试信息的情况下,打开coredump堆栈,并不会直接显示core的代码行,这时可以使用disassemble打开该帧函数的反汇编代码,然后使用汇编代码来判断程序崩溃的地方:(gdb) disassembleDump of assembler code for function __GI_raise: 0x00007f83f70fc3f0 <+0>: mov %fs:0x2d4,%ecx 0x00007f83f70fc3f8 <+8>: mov %fs:0x2d0,%eax 0x00007f83f70fc400 <+16>: movslq %eax,%rsi 0x00007f83f70fc403 <+19>: test %esi,%esi 0x00007f83f70fc405 <+21>: jne 0x7f83f70fc438 <__GI_raise+72> 0x00007f83f70fc407 <+23>: mov $0xba,%eax 0x00007f83f70fc40c <+28>: syscall 0x00007f83f70fc40e <+30>: mov %eax,%ecx 0x00007f83f70fc410 <+32>: mov %eax,%fs:0x2d0 0x00007f83f70fc418 <+40>: movslq %eax,%rsi 0x00007f83f70fc41b <+43>: movslq %edi,%rdx 0x00007f83f70fc41e <+46>: mov $0xea,%eax 0x00007f83f70fc423 <+51>: movslq %ecx,%rdi 0x00007f83f70fc426 <+54>: syscall => 0x00007f83f70fc428 <+56>: cmp $0xfffffffffffff000,%rax 0x00007f83f70fc42e <+62>: ja 0x7f83f70fc450 <__GI_raise+96> 0x00007f83f70fc430 <+64>: repz retq 0x00007f83f70fc432 <+66>: nopw 0x0(%rax,%rax,1) 0x00007f83f70fc438 <+72>: test %ecx,%ecx 0x00007f83f70fc43a <+74>: jg 0x7f83f70fc41b <__GI_raise+43> 0x00007f83f70fc43c <+76>: mov %ecx,%edx 0x00007f83f70fc43e <+78>: neg %edx—Type <return> to continue, or q <return> to quit—