gdb调试程序

GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c/c++程序员,gdb是必不可少的工具;虽然它是命令行模式的调试工具,但是它的功能强大到你无法想象,能够让用户在程序运行时观察程序的内部结构和内存的使用情况。

安装gdb

如果没有安装gdb则可以通过yum install 来安装下。

[root@localhost tools]# yum install -y gdb
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
 * base: ftp.sjtu.edu.cn
 * centos-sclo-rh: mirrors.cqu.edu.cn
 * centos-sclo-sclo: ftp.sjtu.edu.cn
 * extras: ftp.sjtu.edu.cn
 * updates: mirrors.ustc.edu.cn
base                                                                                                                                | 3.6 kB  00:00:00     
centos-sclo-rh                                                                                                                      | 3.0 kB  00:00:00     
centos-sclo-sclo                                                                                                                    | 3.0 kB  00:00:00     
extras                                                                                                                              | 2.9 kB  00:00:00     
updates                                                                                                                             | 2.9 kB  00:00:00     
Package gdb-7.6.1-120.el7.x86_64 already installed and latest version
Nothing to do
[root@localhost tools]# 

gbd基本使用

启动gdb的调用语法:

gdb 目标程序
gdb -q 目标程序 //表示不打印gdb版本信息,界面较为干净;

gdb常用命令:

命令简写命令说明
set args设置程序运行的参数,比如说./Main 张三 李四 我喜欢你; 则设置参数的方法为 set args 张三 李四 我喜欢你
breakb设置断点,b 20 表示在第20行设置断点,可以设置多个断点。
runr开始/重新运行程序, 程序运行到断点的位置会停下来,如果没有遇到断点,程序一直运行下去。
nextn执行当前行语句,如果该语句为函数调用,不会进入函数内部。 VS的F10
steps执行当前行语句,如果该语句为函数调用,则进入函数内部。如果是库函数或者第三方库函数,则进不到函数内部,因为没有源代码,只要有源码的地方都能进去。VS的F11
printp显示变量或表达式的值,如果是指针变量则显示指针指向的变量的地址。 如果p后面是表达式,会执行这个表达式。还可以作为变量的赋值语句来用
continuec继续运行程序,遇到下一个断点停止,如果没有遇到断点,程序将一直运行。VS的F5
set var设置变量的值,假如程序中定义了两个变量 int i; char name[21]; set var i = 10086 set var name = “JacksonWang”
quitq退出gdb
start单步执行,运行程序,并停留在第一个执行语句。
finsh在进入到函数内部的情况下,结束当前函数,回到函数调用点
backtracebt查函数调用堆栈
until当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。until+行号: 运行至某行,不仅仅用来跳出循环
b 23 if a>b条件断点设置, if后面跟着条件。

这里用c++程序做基本演示。c程序也是同样的道理的。

#include<iostream>
using namespace std;

void Show(const char* forName,const char* toName,const char* speakMsg)
{
    cout << forName  << "开始向" << toName << "表白。" << endl;
    cout << speakMsg << endl;
    cout << forName << "表白完成!" << endl; 
}


int main(int argc,char* argv[],char* envp[])
{

    if(argc != 4)
    {
        
        cout << "神级表白神器SDK的使用方法: ./Main 追求者姓名 被追求者姓名 表白内容" << endl;
        return -1;
    }


    cout << "表白前的预处理工作1" << endl;
    cout << "表白前的预处理工作2" << endl;
    cout << "表白前的预处理工作3" << endl;
    cout << "表白前的预处理工作4" << endl;
    Show(argv[1],argv[2],argv[3]);
    cout << "表白完成!" << endl;    

    //这里开始使用条件断点,玩一下
    for (size_t i = 0; i < 10; i++)
    {
        string str = "这是第" + to_string(i) + "个超级女生。" ;
        cout << str << endl;
    }
    
    return 0;
   
}

注意,如果希望你的程序可调试,编译时需要加-g选项,并且,不能使用-O的优化选项。

INCLUDE_DIR=-I /root/api -I /root/tools 
LIB_DIR=-L /root/api/ -l myapi -L /root/tools -l  public 
all:HelloWorld HelloWorld_1 Main
HelloWorld:HelloWorld.cpp
	g++ -o HelloWorld HelloWorld.cpp $(LIB_DIR) $(INCLUDE_DIR)
	cp HelloWorld ./temp
	./HelloWorld
HelloWorld_1:Helloworld_1.cpp
	g++ -o HelloWorld_1 Helloworld_1.cpp $(LIB_DIR) $(INCLUDE_DIR)
# 为了可执行生成可以调试,g++ 加入 -g附加参数
Main:Main.cpp
	g++ -g -o Main  Main.cpp 	
clean:
	rm -rf HelloWorld \
	rm -rf HelloWorld_1\
	rm -rf Main

# 跑一下程序
root@localhost app]# make
g++ -g -o Main  Main.cpp 
[root@localhost app]# ./Main 张三 李四 我爱你
表白前的预处理工作1
表白前的预处理工作2
表白前的预处理工作3
表白前的预处理工作4
张三开始向李四表白。
我爱你
张三表白完成!
这是第0个超级女生。
这是第1个超级女生。
这是第2个超级女生。
这是第3个超级女生。
这是第4个超级女生。
这是第5个超级女生。
这是第6个超级女生。
这是第7个超级女生。
这是第8个超级女生。
这是第9个超级女生。
[root@localhost app]# 

#开始调试
[root@localhost app]# gdb Main
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/app/Main...done.
# 设置程序运行参数
(gdb) set args 张三 李四 我喜欢你
# 23行来一个断点
(gdb) b 23
Breakpoint 1 at 0x400ffc: file Main.cpp, line 23.
# 直接跳转到断点会失效,因为调试之前必须开始调试
(gdb) c
The program is not being run.
# 开始调试,程序在第一个断点处停止
(gdb) r
Starting program: /root/app/Main 张三 李四 我喜欢你
Breakpoint 1, main (argc=4, argv=0x7fffffffdce8, envp=0x7fffffffdd10) at Main.cpp:23
23          cout << "表白前的预处理工作1" << endl;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-317.el7.x86_64 libgcc-4.8.5-44.el7.x86_64 libstdc++-4.8.5-44.el7.x86_64
# 设置第二个断点
(gdb) b 27 
Breakpoint 2 at 0x40106c: file Main.cpp, line 27.
# 直接切到第二个断点
(gdb) c
Continuing.
表白前的预处理工作1
表白前的预处理工作2
表白前的预处理工作3
表白前的预处理工作4
# 第二个断点是一处函数调用
Breakpoint 2, main (argc=4, argv=0x7fffffffdce8, envp=0x7fffffffdd10) at Main.cpp:27
27          Show(argv[1],argv[2],argv[3]);
#步入函数实现
(gdb) s
Show (forName=0x7fffffffdfb2 "张三", toName=0x7fffffffdfb9 "李四", speakMsg=0x7fffffffdfc0 "我喜欢你") at Main.cpp:6
6           cout << forName  << "开始向" << toName << "表白。" << endl;
(gdb) s
张三开始向李四表白。
7           cout << speakMsg << endl;
(gdb) n
我喜欢你
8           cout << forName << "表白完成!" << endl; 
(gdb) n
张三表白完成!
9       }
(gdb) n
main (argc=4, argv=0x7fffffffdce8, envp=0x7fffffffdd10) at Main.cpp:29
29          for (size_t i = 0; i < 10; i++)
(gdb) n
31              string str = "这是第" + to_string(i) + "个超级女生。" ;
# 查局部变量 使用表达式之后的值,这里直接查这个字符串长度
(gdb) p strlen(str)
$1 = 4
(gdb) 
# 查局部变量值
(gdb) p str
$2 = ""
(gdb) n
32              cout << str << endl;
(gdb) p str
$3 = "这是第0个超级女生。"
(gdb) 

gdb设置变量值

[root@localhost app]# gdb Main
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/app/Main...done.
(gdb) set args 张三 李四 我喜欢你
(gdb) b 28
Breakpoint 1 at 0x401098: file Main.cpp, line 28.
(gdb) r
Starting program: /root/app/Main 张三 李四 我喜欢你
表白前的预处理工作1
表白前的预处理工作2
表白前的预处理工作3
表白前的预处理工作4
张三开始向李四表白。
我喜欢你
张三表白完成!

Breakpoint 1, main (argc=4, argv=0x7fffffffdce8, envp=0x7fffffffdd10) at Main.cpp:28
28          cout << "表白完成!" << endl;    
Missing separate debuginfos, use: debuginfo-install glibc-2.17-317.el7.x86_64 libgcc-4.8.5-44.el7.x86_64 libstdc++-4.8.5-44.el7.x86_64
(gdb) n
表白完成!
31          for (size_t i = 0; i < 10; i++)
(gdb) n
33              string str = "这是第" + to_string(i) + "个超级女生。" ;
(gdb) n
34              cout << str << endl;
(gdb) n
这是第0个超级女生。
33              string str = "这是第" + to_string(i) + "个超级女生。" ;
# 查局部变量i的值
(gdb) p i
$1 = 0
# 设置局部变量i值为6之后,这个FOR循环要跑10次的,只跑了4次。
(gdb) set var i=6
(gdb) c
Continuing.
这是第7个超级女生。
这是第8个超级女生。
这是第9个超级女生。
[Inferior 1 (process 5114) exited normally]

[root@localhost app]# gdb Main
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/app/Main...done.
(gdb) b 31 
Breakpoint 1 at 0x4010b4: file Main.cpp, line 31.
(gdb) r
Starting program: /root/app/Main 
神级表白神器SDK的使用方法: ./Main 追求者姓名 被追求者姓名 表白内容
[Inferior 1 (process 5903) exited with code 0377]
Missing separate debuginfos, use: debuginfo-install glibc-2.17-317.el7.x86_64 libgcc-4.8.5-44.el7.x86_64 libstdc++-4.8.5-44.el7.x86_64
(gdb) set args 张三 李四 我喜欢你
(gdb) r
Starting program: /root/app/Main 张三 李四 我喜欢你
表白前的预处理工作1
表白前的预处理工作2
表白前的预处理工作3
表白前的预处理工作4
张三开始向李四表白。
我喜欢你
张三表白完成!
表白完成!
Breakpoint 1, main (argc=4, argv=0x7fffffffdce8, envp=0x7fffffffdd10) at Main.cpp:31
31          for (size_t i = 0; i < 10; i++)
(gdb) n
33              string str = "这是第" + to_string(i) + "个超级女生。" ;
(gdb) p i
$1 = 0
# 设置 变量 i的值的另一种方式 p 变量 = 变量值
(gdb) p i = 8
$2 = 8
(gdb) n
34              cout << str << endl;
(gdb) n
这是第8个超级女生。
33              string str = "这是第" + to_string(i) + "个超级女生。" ;
(gdb) p i 
$3 = 8
(gdb) c
Continuing.
这是第9个超级女生。
[Inferior 1 (process 5979) exited normally]
(gdb) 

gdb调试Core文件

Core Dump:Core的意思是内存,Dump的意思是扔出来,堆出来(段错误)。开发和使用Unix程序时,有时程序莫名其妙的down了,却没有任何的提示(有时候会提示core dumped),这时候可以查看一下有没有形如core.进程号的文件生成,这个文件便是操作系统把程序down掉时的内存内容扔出来生成的, 它可以做为调试程序的参考,能够很大程序帮助我们定位问题。那怎么生成Core文件呢?

产生coredump的条件,首先需要确认当前会话的ulimit –c,为无限制即unlimied . 若为0,则不会产生对应的coredump,需要进行修改和设置。我们可以通过ulimit -c 来查系统资源限制中的core file 文件大小。

在这里插入图片描述

因为我们需要coredump,所以我们需要让core文件能够产生,设置core大小为无限:

ulimit -c unlimied

在实际开发时,我们还得更改core dump 文件的生成目录。

因为core dump默认会生成在程序的工作目录,但是有些程序存在切换目录的情况,导致core dump生成的路径没有规律。所以最好是自己建立一个文件夹,存放生成的core文件。

笔者这里建立一个 /data/coredump 文件夹,即表示在根目录data里的coredump文件夹,来作为统一管理coredump

首先通过修改/proc/sys/kernel/core_pattern来控制core文件保存位置和文件格式。

vim /etc/sysctl.conf
## 最后增加一行
kernel.core_pattern = /data/coredump/core-%e-%p-%t # 也可以使用相对路径,需要确保目录已经存在
kernel.core_uses_pid=0 # 不在文件名后加上pid

达到将core文件统一生成到/data/coredump目录下并产生的文件名为core-命令名-pid-时间戳的目的。

以下是参数列表:
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加命令名

最后,重启后生效,或者执行sysctl -p立即生效。

下面来演示下如果根据Coredump文件来排查程序崩溃问题的做法。

#include <cstring>
#include <iostream>
using namespace std;

void MemeryError(const int bh,const string xm)
{

  char *ptr=nullptr;
  *ptr=3; //空指针解引用赋值 必然内存泄漏
  //strcpy(ptr,xm.c_str()); // 把内容赋值给一段不存在的空间,必然内存泄漏
}

void DoYourBiz(const int no,const string name)
{
  MemeryError(3,"xxxx2");
}

int main()
{
  DoYourBiz(8,"xxxx");

  return 0;
}
[root@localhost app]# make
g++ -g -o Main  Main.cpp 
# 跑程序,因为内存泄漏程序崩了,会提示 Segmentation fault (core dumped)
[root@localhost app]# ./Main 
Segmentation fault (core dumped)
# 开始验尸分析原因,查当前目录没有生成崩盘的core文件,默认Linux是不生成core文件的
[root@localhost app]# ls
HelloWorld  HelloWorld_1  Helloworld_1.cpp  HelloWorld_1.cpp  HelloWorld.cpp  Main  Main.cpp  makefile  temp
# 查Linux系统资源限制情况,即查知是否能生成 Core文件, 因为  core file size = 0 所以不能生成
[root@localhost app]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3766
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 4096
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3766
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
# 开始Core文件生成模式
[root@localhost app]# ulimit -c unlimited
# 再查是否激活Core文件生成模式是否成功激活。
[root@localhost app]# ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3766
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 4096
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3766
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
# 再跑程序,程序继续崩。
[root@localhost app]# ./Main 
Segmentation fault (core dumped)
#再查目录内文件情况,清晰可见core.6507 即有验尸文件了
[root@localhost app]# ls
core.6507  HelloWorld  HelloWorld_1  Helloworld_1.cpp  HelloWorld_1.cpp  HelloWorld.cpp  Main  Main.cpp  makefile  temp
# 用gdb分析Core文件
[root@localhost app]# gdb Main core.6507 
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/app/Main...done.
[New LWP 6507]
Core was generated by `./Main'.
# 很明确告诉你是哪一个函数,哪一个语句报错了导致内存泄漏,进而引发程序崩溃了
Program terminated with signal 11, Segmentation fault.
#0  0x0000000000400869 in MemeryError (bh=3, xm=...) at Main.cpp:9
9         *ptr=3; //空指针解引用赋值 必然内存泄漏
Missing separate debuginfos, use: debuginfo-install glibc-2.17-317.el7.x86_64 libgcc-4.8.5-44.el7.x86_64 libstdc++-4.8.5-44.el7.x86_64
# 再查函数调用栈,这就很清晰了!
(gdb) bt
#0  0x0000000000400869 in MemeryError (bh=3, xm="xxxx2") at Main.cpp:9
#1  0x00000000004008b1 in DoYourBiz (no=8, name="xxxx") at Main.cpp:16
#2  0x0000000000400927 in main () at Main.cpp:21
(gdb) 

假设程序员去修改,然后解决了空指针解引用的问题,又继续错误使用strcpy() 系统又崩了。因为是用库函数挂掉了,我们看不了库函数的实现,而问题就是出现了库函数实现内部。这种问题在实际开发中,一旦不及时判空下,会出现这种问题。

#include <cstring>
#include <iostream>
using namespace std;

void MemeryError(const int bh,const string xm)
{

  char *ptr=nullptr;
  //*ptr=3; //空指针解引用赋值 必然内存泄漏
  strcpy(ptr,xm.c_str()); // 把内容赋值给一段不存在的空间,必然内存泄漏
}

void DoYourBiz(const int no,const string name)
{
  MemeryError(3,"xxxx2");
}

int main()
{
  DoYourBiz(8,"xxxx");

  return 0;
}
root@localhost app]# make
g++ -g -o Main  Main.cpp 
# 程序继续崩溃
[root@localhost app]# ./Main 
Segmentation fault (core dumped)
# 产生新的Core文件
[root@localhost app]# ls
core.6507  core.6834  HelloWorld  HelloWorld_1  Helloworld_1.cpp  HelloWorld_1.cpp  HelloWorld.cpp  Main  Main.cpp  makefile  temp
# 继续调试Core文件
[root@localhost app]# gdb Main core.6834
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/app/Main...done.
[New LWP 6834]
Core was generated by `./Main'.
Program terminated with signal 11, Segmentation fault.
#0  0x00007f07facdfa96 in __strcpy_sse2_unaligned () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-317.el7.x86_64 libgcc-4.8.5-44.el7.x86_64 libstdc++-4.8.5-44.el7.x86_64
# 查调用堆栈,并没有告诉你具体哪里报错了,但我们知道是/lib64/libc.so.6这个动态库里面的这个函数出问题了
(gdb) bt 
#0  0x00007f07facdfa96 in __strcpy_sse2_unaligned () from /lib64/libc.so.6
#1  0x0000000000400927 in MemeryError (bh=3, xm="xxxx2") at Main.cpp:11
#2  0x000000000040096c in DoYourBiz (no=8, name="xxxx") at Main.cpp:16
#3  0x00000000004009e2 in main () at Main.cpp:21
(gdb) 

gdb调整正在运行的程序

通常我们开发的程序都是不会终止的,要么时跑在客户端由客户启动和终止。要么就跑在服务端,24小时无间断运行。可执行文件一但被cpu调度在内存中运行,必然产生一个进程,我们的调试也是基于这个进程ID进行的。

VS已经把进程列表内置了,我们只需要找到这个进程名附加以下就可以了。而在Linux中,这部分工作由开发自己完成,我们可以通过ps -ef 命令来查到要调试进程的ID。

#include <unistd.h>
#include <iostream>
using namespace std;

void MsgContrl(const int bh,const string xm)
{
  for (int ii=0;ii<1000000;ii++)
  {
    sleep(1);
    cout << "ii=" << ii << endl;
  }
}

void DoYourBiz(const int no,const string name)
{
  MsgContrl(3,"正在处理XXX消息");
}

int main()
{
  DoYourBiz(8,"非窗口窗口已经构建,正在进行消息处理");

  return 0;
}
# 跑这个程序,会一直输出编号
[root@localhost app]# make
g++ -g -o Main  Main.cpp 
[root@localhost app]# ./Main 
ii=0
ii=1
ii=2
ii=3
ii=4
....
ii=86

由于shell终端会一直输出并刷新,我们无法控制了。所以在vscode 中再添加一个终端。

在这里插入图片描述

# 根据进程名查 进程ID
[root@localhost app]# ps -ef |grep Main
root       4466   2722  0 17:28 ?        00:00:00 /root/.vscode-server/bin/0ee08df0cf4527e40edc9aa28f4b5bd38bbff2b2/node /root/.vscode-server/bin/0ee08df0cf4527e40edc9aa28f4b5bd38bbff2b2/extensions/json-language-features/server/dist/node/jsonServerMain --node-ipc --clientProcessId=2722
root       7083   2766  0 18:17 pts/4    00:00:00 ./Main
root       7372   7147  0 18:18 pts/0    00:00:00 grep --color=auto Main
# gdb -p附加参数 指定正在运行的进程做调试。
# 调试上了,查一个shell窗口你会发现不会继续输出编号了,证实gdb会中断正在运行的程序,来进行调试。
[root@localhost app]# gdb Main -p 7083
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 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-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/app/Main...done.
Attaching to program: /root/app/Main, process 7083
Reading symbols from /lib64/libstdc++.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libstdc++.so.6
Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libm.so.6
Reading symbols from /lib64/libgcc_s.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/libgcc_s.so.1
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib64/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00007efdae4a9840 in __nanosleep_nocancel () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-317.el7.x86_64 libgcc-4.8.5-44.el7.x86_64 libstdc++-4.8.5-44.el7.x86_64
# 退出gdb,再切换去窗口,发现编号又开始从中断处继续输出编号了。
(gdb) quit
A debugging session is active.

        Inferior 1 [process 7083] will be detached.

Quit anyway? (y or n) y
Detaching from program: /root/app/Main, process 7083
[Inferior 1 (process 7083) detached]

# 正常使用调试,前面怎么调试这里就这么调试~
[root@localhost app]# gdb Main -p 7083
(gdb) bt
#0  0x00007efdae4a9840 in __nanosleep_nocancel () from /lib64/libc.so.6
#1  0x00007efdae4a96f4 in sleep () from /lib64/libc.so.6
#2  0x0000000000400aab in MsgContrl (bh=3, xm="正在处理XXX消息") at Main.cpp:9
#3  0x0000000000400b22 in DoYourBiz (no=8, 
    name="非窗口窗口已经构建,正在进行消息处理") at Main.cpp:16
#4  0x0000000000400ba9 in main () at Main.cpp:21
(gdb) n
Single stepping until exit from function __nanosleep_nocancel,
which has no line number information.
0x00007efdae4a96f4 in sleep () from /lib64/libc.so.6
(gdb) n
Single stepping until exit from function sleep,
which has no line number information.
MsgContrl (bh=3, xm="正在处理XXX消息") at Main.cpp:10
10          cout << "ii=" << ii << endl;
(gdb) n
7         for (int ii=0;ii<1000000;ii++)
(gdb) n
9           sleep(1);
(gdb) 
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐