GDB - 调试示例 2

让我们编写另一个程序,该程序将由于未初始化的内存而导致核心转储。

#include <iostream>  
using namespace std; 

void setint(int*, int); 
int main() 
{ 
   int a; 
   setint(&a, 10); 
   cout << a << endl; 
   
   int* b; 
   setint(b, 10); 
   cout << *b << endl; 
   
   return 0; 
} 

void setint(int* ip, int i)
{
   *ip = i; 
}

要启用调试,必须使用 -g 选项编译程序。

$g++ -g crash.cc -o crash

注意:我们使用 g++ 编译器,因为我们使用了 C++ 源代码。

当您在 Linux 机器上运行此程序时,它将产生以下结果:

segmentation fault (core dumped) 

Now let us debug it using gdb:

$ gdb crash 
(gdb) r 
Starting program: /home/tmp/crash 
10 
10 
Program received signal SIGSEGV, Segmentation fault. 
0x4000b4d9 in _dl_fini () from /lib/ld-linux.so.2 

(gdb) where 
#0  0x4000b4d9 in _dl_fini () from /lib/ld-linux.so.2 
#1  0x40132a12 in exit () from /lib/libc.so.6 
#2  0x4011cdc6 in __libc_start_main () from /lib/libc.so.6 

#3  0x080485f1 in _start () 
(gdb) 

遗憾的是,程序不会在用户定义的函数 mainsetint 中崩溃,因此没有有用的跟踪或局部变量信息。在这种情况下,单步执行程序可能更有用。

(gdb) b main 
# Set a breakpoint at the beginning of the function main 

(gdb) r 
# Run the program, but break immediately due to the breakpoint. 

(gdb) n 
# n = next, runs one line of the program 

(gdb) n 
(gdb) s 
setint(int*, int) (ip=0x400143e0, i=10) at crash2.C:20 
# s = step,类似于 next,但它会进入函数。
# 在这种情况下,进入的函数是 setint。

(gdb) p ip 
$3 = (int *) 0x400143e0 

(gdb) p *ip 
1073827128 

*ip 的值是 ip 指向的整数的值。在本例中,它是一个不寻常的值,并且是存在问题的有力证据。本例中的问题是指针从未正确初始化,因此它指向内存中的某个随机区域(地址 0x40014e0)。纯粹是运气好,将值赋给 *ip 的过程不会导致程序崩溃,但它会产生一些问题,导致程序在完成时崩溃。

gdb_debugging_examples.html