gdb调试c++异常,系统调用,库的load,unload,信号异常等.

  1. 捕获C++异常

    • 格式

      • catch throw [regexp] | catch rethrow [regexp] | catch catch [regexp]
    • 说明

      • 以正则表达式的方式指定感兴趣的异常.
      • throw阶段捕获.
      • $_exception获取抛出的什么异常.
      • 无参表示捕获所有.
    • 局限

      • 系统依赖.遵循gnu-v3标准的c++ ABI支持这种断点.
    • 案例

      • 代码

        #include<stdio.h>
        int main(){
                     
                     
           try{
                     
                     
               throw 2;
           }
           catch(int a){
                     
                     
               printf("%d\n",a);
           }
        }
        
        • 文件名test.cpp.
      • 编译执行

        g++ -g test.cpp -o a.out
        gdb -q -ex 'catch throw int' -ex 'r' -ex 'bt' ./a.out
        
      • 查看catch异常的位置

        g++ -g test.cpp -o a.out
        gdb -q -ex 'catch catch int' -ex 'r' -ex 'bt' ./a.out
        
    • 二次抛出

      • 代码

        #include<stdio.h>
        int main(){
                     
                     
           try{
                     
                     
               throw 2;
           }
           catch(int a){
                     
                     
               printf("%d\n",a);
               throw a;
           }
        }
        
      • 编译执行指令

        g++ -g test.cpp -o a.out
        gdb -q -ex 'catch rethrow int' -ex 'r' -ex 'bt' ./a.out
        
  2. 捕获系统调用

    • 格式

      • catch syscall | catch syscall [name | number | group:groupname | g:groupname] ...
    • 说明

      • 无参表示捕获所有系统调用.
      • 有参则捕获指定.
      • 按名字,按系统调用编号,按分组.都可.
    • 案例

      • 代码

        #include<stdio.h>
        int main(){
                     
                     
           try{
                     
                     
               throw 2;
           }
           catch(int a){
                     
                     
               printf("%d\n",a);
           }
        }
        
        • 文件名test.cpp.
      • 编译执行

        g++ -g test.cpp -o a.out
        gdb -q -ex 'catch syscall' -ex 'r' -ex 'bt' ./a.out
        
        • 这里捕获到的是内存分配brk.
      • 捕获printf

        gdb -q -ex 'catch syscall write' -ex 'r' -ex 'bt' ./a.out
        
  3. 捕获库的装载卸载

    • 格式

      • catch load [regexp] | catch unload [regexp]
    • 说明

      • 无参表示所有.
      • 以正则的方式匹配库名.
    • 案例

      • 代码

        #include<stdio.h>
        int main(){
                     
                     
           try{
                     
                     
               throw 2;
           }
           catch(int a){
                     
                     
               printf("%d\n",a);
           }
        }
        
        • 文件名test.cpp.
      • 编译执行

        g++ -g test.cpp -o a.out
        gdb -q -ex 'catch load libc' -ex 'r' -ex 'bt' ./a.out
        
        • 这里捕获libc.可能会有多个匹配.
    • 使用场景

      • 观察某个库的加载卸载,比如dlopen,dlclose之类.
  4. 捕获信号

    • 格式

      • catch signal [signal... | ‘all’]
    • 说明

      • 无参所有信号,gdb默认捕获一些信号.
      • SIG然后tab补全.
    • 常见

      • 捕获因为非法指针访问出问题的位置.
  5. 信号与异常

    • 说明

      • C++的捕获机制,linux下并不是所有的都会被捕获到.
      • 比如:空指针异常和算术异常和指令异常.
      • 或者说信号都不能被异常捕获机制捕获.
    • 信号处理

      • 信号默认处理方式,和信号自定义处理方式.
      • 信号处理进程共享,不会存在线程特有处理方式.
    • 信号分发

      • 信号分发会发给合适的线程.
      • 没有阻塞,在执行的,循环搜索.
      • 分发给指定线程的信号:空指针异常和算术异常和指令异常.
    • 信号处理周期

      • 每次从内核出来会检查进程状态,是否有信号需要处理.SIGPENDING.
    • 信号信息

      • 一般通过siginfo_t打包信号信息,没有内存保存则仅仅是信号值.
    • 信号区分

      • 普通信号0-32.实时信号33-64.
      • 普通信号用set存储(uint位运算),实时信号用队列存储.
      • 普通信号不存在重复的,实时信号可重复.
    • 信号处理函数

      • 一般有默认,但是 SIGKILL == 9不能被自定义,也无法捕获,这种是为了防止牛皮癣,存在干不掉的进程.1号进程就是牛皮癣.

Guess you like

Origin blog.csdn.net/rubikchen/article/details/119950628