常用命令
如果希望程序可以调试,在编译时需要加入-g
选项,该选项告诉编译器生成调试信息,包括行号、变量名、变量值等;并且不能同时使用-O
的优化选项,这可能会改变代码的原始结构和执行流程,进而影响调试。
进入调试的方式:
gdb target-program
或gdb -q target-program
。-q
表示不打印gdb版本信息,界面较为干净。
命令 | 简写 | 说明 |
---|---|---|
set args | 设置程序运行的参数 如需要运行:./demo aa bb cc 则设置方式:set args aa bb cc |
|
break | b | 设置断点 b 20 表示在第20行设置断点,可以设置多个断点 |
info breakpoints | 显示断点 | |
delete breakpoints | d | 删除断点 d 20 表示删除序号为20的断点,不加序号则删除所有断点 |
run | r | 开始/重新运行程序, 程序运行到断点的位置会停下来,如果没有遇到断点,程序一直运行下去 |
next | n | 执行当前行语句,如果该语句为函数调用,不会进入函数内部 |
step | s | 执行当前行语句,如果该语句为函数调用,则进入函数内部。如果是库函数或者第三方库函数,则进不到函数内部,因为没有源代码,只要有源码的地方都能进去 |
p | 显示变量或表达式的值,如果是指针变量则显示指针指向的变量的地址。 如果p后面是表达式,会执行这个表达式。还可以作为变量的赋值语句来用 | |
continue | c | 继续运行程序,遇到下一个断点停止,如果没有遇到断点,程序将一直运行 |
set var | 设置变量的值 存在变量 int i; char name[21]; 设置值 set var i = 10086 set var name = "JacksonWang" |
|
quit | q | 退出gdb |
start | 单步执行,运行程序,并停留在第一个执行语句 | |
finish | 在进入到函数内部的情况下,结束当前函数,回到函数调用点 | |
backtrace | bt | 查函数调用堆栈 |
until | 当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。 until 行号:运行至某行,不仅仅用来跳出循环 |
|
b 23 if a>b | 条件断点设置, if后面跟着条件 |
示例
- 源码
#include <iostream>
#include <string>
using namespace std;
void func(int i, string &s)
{
cout << "i = " << i << " s = " << s << endl;
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
cout << "执行方式:test 编号 姓名" << endl;
cout << "如:test 100 张三" << endl;
return -1;
}
int i = stoi(argv[1]);
string s = argv[2];
func(i, s);
func(i, s);
for (auto i = 0; i < 10; ++i)
{
string s = "第" + to_string(i)+ "个编号";
cout << s << endl;
}
return 0;
}
C++
- 调试过程
[devuser@Rocky8-online gdb调试]$ gdb test
GNU gdb (GDB) Rocky Linux 8.2-20.el8.0.1
Copyright (C) 2018 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".
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:
--Type <RET> for more, q to quit, c to continue without paging--
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...done.
(gdb) set args 100 张三
(gdb) b 23
Breakpoint 1 at 0x4018aa: file main.cpp, line 23.
(gdb) b 25
Breakpoint 2 at 0x4018be: file main.cpp, line 25.
(gdb) b 27
Breakpoint 3 at 0x4018d2: file main.cpp, line 27.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004018aa in main(int, char**) at main.cpp:23
2 breakpoint keep y 0x00000000004018be in main(int, char**) at main.cpp:25
3 breakpoint keep y 0x00000000004018d2 in main(int, char**) at main.cpp:27
(gdb) d 27
No breakpoint number 27.
(gdb) d 3
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004018aa in main(int, char**) at main.cpp:23
2 breakpoint keep y 0x00000000004018be in main(int, char**) at main.cpp:25
(gdb) r
Starting program: /home/devuser/workspace/c_c++/test/gdb调试/test 100 张三
Breakpoint 1, main (argc=3, argv=0x7fffffffded8) at main.cpp:23
23 func(i, s);
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-251.el8_10.2.x86_64 libgcc-8.5.0-22.el8_10.x86_64 libstdc++-8.5.0-22.el8_10.x86_64
(gdb) n
i = 100 s = 张三
Breakpoint 2, main (argc=3, argv=0x7fffffffded8) at main.cpp:25
25 func(i, s);
(gdb) p i
$1 = 100
(gdb) p s
$2 = "张三"
(gdb) set var i = 200
(gdb) s
func (i=200, s="张三") at main.cpp:8
8 cout << "i = " << i << " s = " << s << endl;
(gdb) n
i = 200 s = 张三
9 }
(gdb) n
main (argc=3, argv=0x7fffffffded8) at main.cpp:27
27 for (auto i = 0; i < 10; ++i)
(gdb) n
29 string s = "第" + to_string(i)+ "个编号";
(gdb) n
30 cout << s << endl;
(gdb) n
第0个编号
29 string s = "第" + to_string(i)+ "个编号";
(gdb) n
27 for (auto i = 0; i < 10; ++i)
(gdb) n
29 string s = "第" + to_string(i)+ "个编号";
(gdb) n
30 cout << s << endl;
(gdb) n
第1个编号
29 string s = "第" + to_string(i)+ "个编号";
(gdb) n
27 for (auto i = 0; i < 10; ++i)
(gdb) n
29 string s = "第" + to_string(i)+ "个编号";
(gdb) n
30 cout << s << endl;
(gdb) n
第2个编号
29 string s = "第" + to_string(i)+ "个编号";
(gdb) n
27 for (auto i = 0; i < 10; ++i)
(gdb) n
29 string s = "第" + to_string(i)+ "个编号";
(gdb) n
30 cout << s << endl;
(gdb) n
第3个编号
29 string s = "第" + to_string(i)+ "个编号";
(gdb) until
27 for (auto i = 0; i < 10; ++i)
(gdb)
第4个编号
第5个编号
第6个编号
第7个编号
第8个编号
第9个编号
33 return 0;
(gdb) q
A debugging session is active.
Inferior 1 [process 1959176] will be killed.
Quit anyway? (y or n) y
[devuser@Rocky8-online gdb调试]$
Shell
调试core文件
如果程序在运行时发生了内存错误,会被内核强行终止,提示“段错误”,内存的状态可保存在core
文件中,方便进一步分析查找问题。
注:默认情况下,不会生成core
文件,需要修改系统参数。
调试方式如下:
- 首先使用
ulimit -a
查看系统限制参数
[devuser@Rocky8-online gdb调试]$ 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) 6955
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 262144
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) 6955
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
Shell
- 使用
ulimit -c unlimited
把core file size
改为unlimited
- 运行程序,产生
core
文件 - 运行
gdb target-program core-file
- 在
gdb
中,使用bt
查看函数调用栈
示例
- 源码
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
void func(int i, string &s)
{
cout << "i = " << i << " s = " << s << endl;
}
void corefunc()
{
char *p = nullptr;
*p = 'A';
strcpy(p, "cplusplus");
cout << "p = " << p << endl;
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
cout << "执行方式:test 编号 姓名" << endl;
cout << "如:test 100 张三" << endl;
return -1;
}
int i = stoi(argv[1]);
string s = argv[2];
func(i, s);
func(i, s);
corefunc();
for (auto i = 0; i < 10; ++i)
{
string s = "第" + to_string(i)+ "个编号";
cout << s << endl;
}
return 0;
}
C++
- 调试过程
使用systemd
的系统不会直接产生core
文件,可按如下方法使用coredumpctl
命令生成
[devuser@Rocky8-online gdb调试]$ cat /proc/sys/kernel/core_pattern
|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %e
[devuser@Rocky8-online gdb调试]$ coredumpctl
TIME PID UID GID SIG COREFILE EXE
Sat 2024-11-09 16:12:16 CST 1959992 1000 1000 11 present /home/devuser/workspace/c_c++/test/gdb调试/test
Sat 2024-11-09 16:16:17 CST 1960127 1000 1000 11 present /home/devuser/workspace/c_c++/test/gdb调试/test
Sat 2024-11-09 16:22:23 CST 1960569 1000 1000 11 present /home/devuser/workspace/c_c++/test/gdb调试/test
[devuser@Rocky8-online gdb调试]$ coredumpctl -o core dump 1960569
PID: 1960569 (test)
UID: 1000 (devuser)
GID: 1000 (devuser)
Signal: 11 (SEGV)
Timestamp: Sat 2024-11-09 16:22:23 CST (7min ago)
Command Line: ./test 100
Executable: /home/devuser/workspace/c_c++/test/gdb调试/test
Control Group: /user.slice/user-1000.slice/session-727.scope
Unit: session-727.scope
Slice: user-1000.slice
Session: 727
Owner UID: 1000 (devuser)
Boot ID: 3715d4f161824bbf9481b064cc42f893
Machine ID: 74da068e81f448da853c64463d64e826
Hostname: Rocky8-online
Storage: /var/lib/systemd/coredump/core.test.1000.3715d4f161824bbf9481b064cc42f893.1960569.1731140543000000.lz4
Message: Process 1960569 (test) of user 1000 dumped core.
Stack trace of thread 1960569:
#0 0x00000000004017b7 n/a (/home/devuser/workspace/c_c++/test/gdb调试/test)
#1 0x0000000000401936 n/a (/home/devuser/workspace/c_c++/test/gdb调试/test)
#2 0x00007f182025d7e5 __libc_start_main (libc.so.6)
#3 0x000000000040168e n/a (/home/devuser/workspace/c_c++/test/gdb调试/test)
[devuser@Rocky8-online gdb调试]$ ls -l
total 704
-rw-rw-r--. 1 devuser devuser 499712 Nov 9 16:29 core
drwxrwxr-x. 2 devuser devuser 6 Nov 9 15:12 include
drwxrwxr-x. 2 devuser devuser 6 Nov 9 15:12 lib
-rw-rw-r--. 1 devuser devuser 724 Nov 9 16:11 main.cpp
-rw-rw-r--. 1 devuser devuser 117328 Nov 9 16:12 main.o
-rw-rw-r--. 1 devuser devuser 1428 Nov 9 15:43 Makefile
-rwxrwxr-x. 1 devuser devuser 92672 Nov 9 16:12 test
Shell
[devuser@Rocky8-online gdb调试]$ gdb test core
GNU gdb (GDB) Rocky Linux 8.2-20.el8.0.1
Copyright (C) 2018 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".
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:
--Type <RET> for more, q to quit, c to continue without paging--
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...done.
[New LWP 1960569]
Core was generated by `./test 100 张三'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00000000004017b7 in corefunc () at main.cpp:15
15 *p = 'A';
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-251.el8_10.2.x86_64 libgcc-8.5.0-22.el8_10.x86_64 libstdc++-8.5.0-22.el8_10.x86_64
(gdb) bt
#0 0x00000000004017b7 in corefunc () at main.cpp:15
#1 0x0000000000401936 in main (argc=3, argv=0x7fff0d021a78) at main.cpp:36
(gdb)
Shell
调试正在运行中的程序
gdb target-program -p pid
Shell
示例
- 源码
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
int main(int argc, char *argv[])
{
for (auto i = 0; i < 1000000; ++i)
{
string s = "第" + to_string(i)+ "个编号";
cout << s << endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
}
return 0;
}
C++
- 调试过程
[devuser@Rocky8-online gdb调试]$ ps -ef | grep test
devuser 1954586 1952692 0 13:35 pts/0 00:00:00 gdb test
devuser 1962014 1954938 0 19:00 pts/1 00:00:00 ./test
devuser 1962280 1962066 0 19:01 pts/2 00:00:00 grep --color=auto test
[devuser@Rocky8-online gdb调试]$ gdb test -p 1962014
GNU gdb (GDB) Rocky Linux 8.2-20.el8.0.1
Copyright (C) 2018 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".
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:
--Type <RET> for more, q to quit, c to continue without paging--
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from test...done.
Attaching to program: /home/devuser/workspace/c_c++/test/gdb调试/test, process 1962014
Reading symbols from /lib64/libstdc++.so.6...Reading symbols from .gnu_debugdata for /lib64/libstdc++.so.6...(no debugging symbols found)...done.
(no debugging symbols found)...done.
Reading symbols from /lib64/libm.so.6...Reading symbols from .gnu_debugdata for /lib64/libm.so.6...(no debugging symbols found)...done.
(no debugging symbols found)...done.
Reading symbols from /lib64/libgcc_s.so.1...Reading symbols from .gnu_debugdata for /lib64/libgcc_s.so.1...(no debugging symbols found)...done.
(no debugging symbols found)...done.
Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.
Reading symbols from /lib64/ld-linux-x86-64.so.2...done.
0x00007fdb54a00068 in nanosleep () from /lib64/libc.so.6
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-251.el8_10.2.x86_64 libgcc-8.5.0-22.el8_10.x86_64 libstdc++-8.5.0-22.el8_10.x86_64
(gdb) n
Single stepping until exit from function nanosleep,
which has no line number information.
std::this_thread::sleep_for<long, std::ratio<1l, 1l> > (__rtime=...) at /usr/include/c++/8/thread:379
379 while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
(gdb) n
384 }
(gdb) n
main (argc=1, argv=0x7ffef61ed998) at main.cpp:11
11 string s = "第" + to_string(i)+ "个编号";
(gdb) n
9 for (auto i = 0; i < 1000000; ++i)
(gdb) n
11 string s = "第" + to_string(i)+ "个编号";
(gdb) n
12 cout << s << endl;
(gdb) n
13 std::this_thread::sleep_for(std::chrono::seconds(5));
(gdb) n
n
n
11 string s = "第" + to_string(i)+ "个编号";
(gdb) n
9 for (auto i = 0; i < 1000000; ++i)
(gdb) n
11 string s = "第" + to_string(i)+ "个编号";
(gdb) n
12 cout << s << endl;
(gdb) n
13 std::this_thread::sleep_for(std::chrono::seconds(5));
(gdb) n
n
n
n
n
11 string s = "第" + to_string(i)+ "个编号";
(gdb) n
9 for (auto i = 0; i < 1000000; ++i)
(gdb) n
11 string s = "第" + to_string(i)+ "个编号";
(gdb) n
12 cout << s << endl;
(gdb) n
13 std::this_thread::sleep_for(std::chrono::seconds(5));
(gdb) c
Continuing.
Shell
评论 (0)