1.什么是gdb?
gdb 是 GNU Debugger 的缩写,是一个功能强大的用于调试程序的开源调试器工具。它可以帮助开发人员诊断和解决程序中的错误、跟踪程序执行过程、查看变量的值等。gdb 支持多种编程语言,包括 C、C++、Objective-C、Fortran 等,并可用于多种操作系统,如 Linux、Unix、Windows 等。
通过 gbd,开发人员可以进行如下操作:
-
设置断点:可以在程序中设置断点,以便在执行到特定代码行时暂停程序的执行,方便查看程序状态。
-
单步执行:可以逐行执行程序,并查看每一步的执行情况,帮助定位错误。
-
查看变量:可以查看程序中各个变量的值,帮助分析程序状态。
-
堆栈跟踪:可以查看函数调用栈,帮助理解程序的执行流程。
-
内存管理:可以查看和修改程序的内存内容,有助于发现内存相关的问题。
总的来说,gdb 是一款功能丰富的调试工具,适用于各种编程语言和操作系统,是开发人员在调试程序时的重要利器。通过使用 gdb,开发人员可以更快速地定位和解决程序中的问题,提高开发效率。
2.为什么要用gdb?
因为我使用的是QT开发程序,在开发机上可以不用gdb调试,用QT断点调试就行了,但是
程序发布后,别人的机子是没有开发环境的,这个时候别人用程序崩溃了?怎么办?怎么查找原因?常见的有一下方法:
-
查看错误信息:程序崩溃时通常会输出错误信息或者崩溃日志。您可以查看这些信息,通常会包含有关错误发生的位置和原因。这可以帮助您快速定位问题所在。
-
日志文件:有些程序会将运行时的日志记录在特定的日志文件中。查看这些日志文件可以帮助您了解程序运行过程中的详细信息,从而定位问题。
-
使用系统工具:操作系统通常提供一些工具来帮助诊断程序问题,比如在 Linux 系统中,您可以使用 dmesg 命令查看系统日志,或者使用 gdb 进行程序调试。
-
重现问题:尝试重现程序崩溃的步骤,看看是不是可以稳定地触发问题。这有助于确定问题发生的条件和步骤。
-
编译调试信息:如果可能的话,可以尝试在开发环境中编译程序时加入调试信息,然后将可执行文件拷贝到没有开发环境的电脑上运行。这样在程序崩溃时,可以使用调试器(如 gdb)来分析问题。
-
查看内存情况:程序崩溃有可能是因为内存相关的问题,比如内存泄漏或者访问非法内存。您可以使用内存检测工具(如 Valgrind)来检查程序的内存使用情况。
最常见的就是使用日志,根据最后的输出位置来定位崩溃点的大致方位,但是如果程序比较复杂,有很多个可疑的地方,还是无法很棘手,不好确定,如下所示,只知道获取到了用户信息后就崩溃了,访问了非法的内存,其他原因一无所知
所以除了日志,还得需要辅助工具来确认具体的崩溃点,linux下用gdb就行了,他会在程序崩溃时,输出具体的崩溃日志信息,哪个函数,哪个类,什么原因导致的
3. linux下怎么使用gdb?
我用最简单的方法使用,每台linux,装机就自带了gdb,所以直接用就行了
1. 用gdb运行程序
终端输入:gdb 要运行的程序名称
如下所示,运行后,会进入gdb控制界面,你可以输入指令进行断点调试,直接运行程序等
因为我要直接找崩溃的点,我就直接运行了,这样运行不会影响程序,和正常运行程序一样,直到程序崩溃或者退出
2. 输入直接运行程序的指令
输入:run,然后回车运行程序
3.正常使用程序,直到程序崩溃了卡住
程序卡住后,去看终端gdb输出
然后回车,你会看到一些崩溃原因的输出信息,然后等待你的下一步指令
根据崩溃信息:Thread 41 "Thread (pooled)" received signal SIGSEGV, Segmentation fault.
可以知道是由于内存引起的崩溃,内存引起的崩溃有一下原因:
-
内存泄漏(Memory Leaks):
- 内存泄漏是指程序在动态分配内存后,没有正确释放该内存,导致系统中的可用内存不断减少,最终可能导致程序崩溃。频繁的内存分配而不释放还会导致程序性能下降。
-
野指针(Dangling Pointers):
- 当程序试图访问已经释放的内存,或者已经超出作用域的内存时,就会产生野指针。使用野指针访问内存会导致未定义行为,可能导致程序崩溃。
-
访问非法内存(Access Violation):
- 尝试访问未分配或者越界的内存空间会导致访问非法内存。这会触发操作系统的保护机制,通常会导致程序崩溃。
-
内存重叠(Memory Overlapping):
- 当两个或多个动态分配的内存块发生重叠时,可能会导致未定义行为,包括程序崩溃。
-
栈溢出(Stack Overflow):
- 当程序递归调用层次过深或者在栈上分配过多的局部变量时,栈空间可能会耗尽,导致栈溢出,从而导致程序崩溃。
在根据崩溃信息:0x00007ffff5fc991c in QString::operator=(QString const&) () from
可以知道是=赋值时崩溃的,但具体是哪个地方的赋值引起的,还不知道,需要更多的崩溃信息
4. 输入指令查看详细的崩溃信息
4.1 输入bt
在 GDB(GNU调试器)中,输入 bt
命令可以打印出当前的函数调用栈(backtrace),也就是显示当前程序执行过程中的函数调用关系。这个函数调用栈显示了从程序入口到当前位置之间所有的函数调用关系,通常用于调试程序时查看导致程序崩溃或异常的函数调用路径。
bt
命令会显示函数调用栈的详细信息,包括每个调用帧(frame)的函数名、源文件名、行号等信息。通过查看函数调用栈,开发人员可以了解程序崩溃时各个函数之间的调用关系,从而更好地定位问题所在。
所以我一般用bt就够了,在终端输入:bt
可以看到程序崩溃时各个函数之间的调用关系,结合你的程序源代码,基本可以锁定崩溃点了
我的崩溃点在这里,查询组织机构时,但是为空,赋值时崩溃的
把上面这个输出的日志信息和这个崩溃信息函数调用图给研发人员看,即可
4.2 循环输入ret
输入ret, 在输入y确认,可以选择让当前的栈帧立即返回,立即返回当前的栈帧,重复输入,可以返回在返回,直到输出了看不懂的输出
知道大概原因后,输入n 退出回溯当前的栈帧
4.3 其他指令
在 GDB 中,有一些其他常用的指令可以帮助您查看程序崩溃的原因、位置以及相关信息。以下是一些与调试程序崩溃相关的 GDB 指令:
-
info registers
:显示当前 CPU 寄存器的值,帮助您了解程序崩溃时寄存器状态,有助于定位问题。 -
info frame
:显示当前帧的信息,包括函数参数、局部变量等,帮助您了解当前函数的上下文信息。 -
info locals
:显示当前函数的局部变量及其值,有助于您查看程序崩溃时局部变量的状态。 -
info breakpoints
:显示当前设置的断点信息,可以查看程序中所有已设置的断点。 -
info line
:显示当前执行代码行的源代码位置,帮助您了解程序崩溃时所在的源代码位置。 -
info stack
:显示当前线程的调用栈信息,包括函数调用顺序和参数值,有助于定位程序崩溃时的函数调用路径。 -
info threads
:显示当前程序的所有线程信息,可以查看各个线程的状态和调用栈信息,帮助您分析多线程程序的崩溃情况。 -
thread apply all bt
:显示所有线程的函数调用栈信息,帮助您同时查看多个线程的调用栈,有助于分析多线程程序的崩溃情况。
5. 退出gdb
输出quit,回车,在输入y确认即可退出
4.没有运行gdb的情况下,怎么查看崩溃信息
查看core dump 文件
core dump 文件是在程序发生严重错误(如段错误、内存访问错误等)并终止时,操作系统生成的包含程序内存状态的文件。这个文件可以帮助开发人员在程序崩溃时分析问题并进行调试。
要生成 core dump 文件,您可以按照以下步骤进行:
-
确保核心转储(core dump)被启用:
在大多数 Unix/Linux 系统中,默认情况下核心转储功能可能是禁用的。您可以通过设置以下命令来启用核心转储:
ulimit -c unlimited
这将允许您的程序生成核心转储文件。如果您想要将核心转储文件存放在特定目录,可以使用以下命令:
echo "/path/to/dumpfiles/core-%e.%p" > /proc/sys/kernel/core_pattern
并假设您的可执行文件为
my_program
,假设您希望在/var/coredumps/
目录下存储 core dump 文件,那么您可以设置模式为:echo "/var/coredumps/core-%e.%p" > /proc/sys/kernel/core_pattern
这样,当
my_program
发生崩溃时,系统将生成一个 core dump 文件,并将其命名为类似于core-my_program.12345
的文件,其中12345
是进程的 ID。这个设置将使系统在发生崩溃时将 core dump 文件保存在
/var/coredumps/
目录下,并根据可执行文件的名称和进程 ID 命名生成的文件 -
运行程序并导致程序崩溃:
现在,当您运行程序并导致程序崩溃时,操作系统将生成一个包含程序崩溃时内存状态的 core dump 文件。
-
查看 core dump 文件:
您可以使用 GDB 来查看 core dump 文件,如之前所述的步骤:
如gdb ./test -c core
格式:gdb <your_program_executable> -c <core_dump_file>
-
在 GDB 中分析 core dump 文件:
一旦您加载了 core dump 文件,您可以使用 GDB 的各种命令来分析程序在崩溃时的状态,包括查看堆栈回溯、寄存器状态等。
注意,生成核心转储文件可能会占用大量磁盘空间,因此请根据需要进行清理