前言

// Offers opportunities to play with pointers with GDB
/*
gcc -g bar.c -o bar //-g compile with debug info for gdb
*/
# include <stdio.h>

int foo(int n);
void bar(int m);

int main(void)
{
    int a;
    char *s = "hello, world";
    printf("%s\n", &s[7]);
    a = 5;
    foo(a);
    return 0;
}

int foo(int n)
{
    int b;
    b = n;
    b *= 2;
    bar(b);
    return b;
}

void bar(int m)
{
    printf("Hi, I'm bar.\n");
}

首先编译该程序,添加-g选项可以给编译程序添加debug信息。

# gcc -g bar.c -o bar //-g compile with debug info for gdb

调试开始:

...
Reading symbols from bar...done.
(gdb) break main                               # 在main函数上打断点,程序在进入main函数后暂停
Breakpoint 1 at 0x40052e: file bar.c, line 9.
(gdb) run                                      # run指令运行程序
Starting program: /home/wangx/test/bar

Breakpoint 1, main () at bar.c:9
9	    char *s = "hello, world";          # 程序停止在这里意味着这行下一步将被执行但是还没有执行
(gdb) list                                     # 显示停顿处周围的代码
4	void bar(int m);
5
6	int main(void)
7	{
8	    int a;
9	    char *s = "hello, world";
10	    printf("%s\n", &s[7]);
11	    a = 5;
12	    foo(a);
13	    return 0;
(gdb) print a                                   # 显示a的值,此时a没被赋值,是内存中的一个无效数字
$1 = 32767
(gdb) print &a                                  # 显示a的地址
$2 = (int *) 0x7fffffffe4d4
(gdb) next                                      # 运行程序到当前函数下一行停止
10	    printf("%s\n", &s[7]);
(gdb) next                                      # next again
world
11	    a = 5;
(gdb) next                                      # next again,看见下一行将进入foo函数
12	    foo(a);
(gdb) step                                      # 运行程序到最近位置停下,这里的作用是进入到foo函数中停止
foo (n=5) at bar.c:19
19	    b = n;
(gdb) print n                                   # 显示n的值
$3 = 5
(gdb) print b                                   # 显示b的值,b还没被赋值
$4 = 32767
(gdb) print &b                                  # 显示b的地址
$5 = (int *) 0x7fffffffe4bc
(gdb) continue                                  # 程序继续执行直到下一个断点停止
Continuing.
Hi, I'm bar.
[Inferior 1 (process 28376) exited normally]    #程序退出

该例子还说明了被调用的函数中变量的地址更小。即新调用的栈的地址更小。具体来说,这里main函数调用了foo函数,main中a变量的地址为0x7fffffffe4d4,foo中b变量的地址为0x7fffffffe4bc,显然b的地址比a小,说明越高的栈在本机中地址是越小的。

         +-------------+                            0
         |     ...     |                            ^
         +-------------+                            |
memory-> |  foo(a), b  | ---> smaller address       |
         +-------------+                            |
         |    main, a  | ---> bigger address        v
         +-------------+                       最大内存位置

GDB 常用指令