gdb 调试程序常用指令

07-19 859阅读

gdb调试程序常用指令

GDB(GNU Debugger)是一个功能强大的调试工具,广泛用于调试C、C++等编程语言的程序。深入理解GDB的使用可以大大提高程序开发和调试的效率。下面我们通过多个具体的例子来详细介绍GDB的使用方法和技巧。

gdb 调试程序常用指令
(图片来源网络,侵删)

1. 启动GDB

首先,确保编译时使用了 -g 选项以包含调试信息:

$ gcc -g example.c -o example

启动GDB:

$ gdb example

2. 设置断点和运行程序

示例代码:

#include 
void greet() {
    printf("Hello, World!\n");
}
int main() {
    greet();
    printf("Goodbye, World!\n");
    return 0;
}

在main函数入口设置断点并运行:

(gdb) break main
Breakpoint 1 at 0x40052e: file example.c, line 9.
(gdb) run
Starting program: /path/to/example
Breakpoint 1, main () at example.c:9
9       greet();

3. 单步执行和检查变量

单步执行并检查变量:

(gdb) step
greet () at example.c:5
5       printf("Hello, World!\n");
(gdb) step
Hello, World!
6   }
(gdb) step
main () at example.c:10
10      printf("Goodbye, World!\n");
(gdb) print 0
$1 = 0

4. 观察点(Watchpoints)

示例代码:

#include 
int counter = 0;
void increment() {
    counter++;
}
int main() {
    increment();
    increment();
    return 0;
}

在变量counter上设置观察点:

(gdb) break main
Breakpoint 1 at 0x40052e: file example.c, line 11.
(gdb) run
Starting program: /path/to/example
Breakpoint 1, main () at example.c:11
11      increment();
(gdb) watch counter
Hardware watchpoint 2: counter
(gdb) continue
Continuing.
Hardware watchpoint 2: counter
Old value = 0
New value = 1
increment () at example.c:6
6       counter++;

5. 查看调用栈和帧

查看调用栈和切换帧:

(gdb) backtrace
#0  increment () at example.c:6
#1  0x000000000040052f in main () at example.c:12
(gdb) frame 0
#0  increment () at example.c:6
6       counter++;
(gdb) frame 1
#1  0x000000000040052f in main () at example.c:12
12      increment();

6. 修改变量值

示例代码:

#include 
int main() {
    int a = 5;
    int b = 10;
    printf("a + b = %d\n", a + b);
    return 0;
}

在运行时修改变量值:

(gdb) break main
Breakpoint 1 at 0x40052e: file example.c, line 5.
(gdb) run
Starting program: /path/to/example
Breakpoint 1, main () at example.c:5
5       int a = 5;
(gdb) next
6       int b = 10;
(gdb) print a
$1 = 5
(gdb) set var a = 20
(gdb) print a
$2 = 20
(gdb) continue
a + b = 30

7. 调试核心文件

生成核心文件:

$ ulimit -c unlimited
$ ./example
Segmentation fault (core dumped)

使用GDB调试核心文件:

$ gdb example core

示例代码:

#include 
int main() {
    int *p = NULL;
    *p = 5;  // 引发段错误
    return 0;
}

调试核心文件查看崩溃原因:

(gdb) run
Starting program: /path/to/example
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400526 in main () at example.c:5
5       *p = 5;
(gdb) backtrace
#0  0x0000000000400526 in main () at example.c:5

8. 调试多线程程序

示例代码:

#include 
#include 
void* thread_func(void* arg) {
    printf("Thread %d\n", *(int*)arg);
    return NULL;
}
int main() {
    pthread_t t1, t2;
    int id1 = 1, id2 = 2;
    pthread_create(&t1, NULL, thread_func, &id1);
    pthread_create(&t2, NULL, thread_func, &id2);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    return 0;
}

调试多线程程序:

(gdb) break main
(gdb) run
(gdb) info threads
(gdb) thread 2
(gdb) backtrace
(gdb) continue

通过这些具体的例子,我们可以看到GDB在设置断点、单步执行、检查和修改变量、查看调用栈、调试多线程程序等方面的强大功能。熟练掌握这些技巧可以大大提高调试效率和程序的可靠性。

多线程调试深入分析

多线程程序的调试相对复杂,因为多个线程同时执行,导致调试过程变得更加难以控制和理解。GDB提供了一些专门用于多线程调试的命令和功能,下面通过详细说明和举例来加深对多线程调试的理解。

1. 基本概念

  • 线程(Thread):一个线程是一个独立执行的最小单元。
  • 主线程(Main Thread):创建其他线程的主程序中的线程。
  • 线程ID(Thread ID):GDB为每个线程分配一个唯一的ID来区分不同的线程。

    2. 常用命令

    • info threads:列出所有线程及其状态。
    • thread [id]:切换到指定的线程。
    • thread apply [id|all] [command]:对一个或多个线程执行GDB命令。

      3. 示例代码

      以下是一个简单的多线程程序,用于演示如何使用GDB进行调试:

      #include 
      #include 
      #include 
      void* thread_func(void* arg) {
          int id = *(int*)arg;
          for (int i = 0; i  
      

      编译并运行程序:

      $ gcc -g -pthread example.c -o example
      $ ./example

      4. 调试多线程程序

      启动GDB并设置断点:

      $ gdb example
      (gdb) break thread_func
      Breakpoint 1 at 0x40052d: file example.c, line 7.
      (gdb) run
      Starting program: /path/to/example

      查看线程信息:

      (gdb) info threads
        Id   Target Id         Frame 
      * 1    Thread 0x7ffff7fb6740 (LWP 1234) "example" main () at example.c:15
        2    Thread 0x7ffff7fb5700 (LWP 1235) "example" thread_func (arg=0x7fffffffe4c) at example.c:7
        3    Thread 0x7ffff7fb4700 (LWP 1236) "example" thread_func (arg=0x7fffffffe4c) at example.c:7

      切换到特定线程并检查栈帧:

      (gdb) thread 2
      [Switching to thread 2 (Thread 0x7ffff7fb5700 (LWP 1235))]
      (gdb) backtrace
      #0  thread_func (arg=0x7fffffffe4c) at example.c:7
      #1  0x00007ffff7bc6fa3 in start_thread (arg=) at pthread_create.c:486
      #2  0x00007ffff78ed4cf in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

      单步执行特定线程:

      (gdb) step
      Thread 2: 0
      (gdb) step
      Thread 2: 1

      对所有线程执行命令:

      (gdb) thread apply all backtrace
      Thread 3 (Thread 0x7ffff7fb4700 (LWP 1236)):
      #0  thread_func (arg=0x7fffffffe4c) at example.c:7
      #1  0x00007ffff7bc6fa3 in start_thread (arg=) at pthread_create.c:486
      #2  0x00007ffff78ed4cf in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
      Thread 2 (Thread 0x7ffff7fb5700 (LWP 1235)):
      #0  thread_func (arg=0x7fffffffe4c) at example.c:7
      #1  0x00007ffff7bc6fa3 in start_thread (arg=) at pthread_create.c:486
      #2  0x00007ffff78ed4cf in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
      Thread 1 (Thread 0x7ffff7fb6740 (LWP 1234)):
      #0  main () at example.c:15

      设置线程特定断点:

      (gdb) break thread_func thread 2
      (gdb) continue
      Continuing.
      Thread 2 hit Breakpoint 1, thread_func (arg=0x7fffffffe4c) at example.c:7
      7       for (int i = 0; i  
      

      5. 综合调试示例

      以下是一个综合示例,展示了如何使用GDB调试多线程程序的各个方面:

      1. 启动GDB并设置断点:

        $ gdb example
      2. 设置断点并运行程序:

        (gdb) break thread_func
        (gdb) run
      3. 程序暂停时查看线程:

        (gdb) info threads
      4. 切换到特定线程:

        (gdb) thread 2
      5. 查看调用栈:

        (gdb) backtrace
      6. 单步执行:

        (gdb) step
      7. 对所有线程执行命令:

        (gdb) thread apply all backtrace
      8. 继续执行程序:

        (gdb) continue

      通过这些详细步骤,我们可以全面了解如何使用GDB调试多线程程序,掌握线程切换、查看调用栈、单步执行等技巧,以更有效地定位和解决多线程程序中的问题。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]