基本概念(4)——调试器

运行lldb

lldb main.out
或者直接lldb,进入后 使用file main.out指定要调试的文件
注意:运行之前要clang++ -g,一定要有-g参数才能用lldb调试。
另一种执行:lldb main.out example1 假设可执行程序名为 main.out,参数为 example1
qquit 离开lldb

tab键

支持tab键联想,输入br然后按下tab就会联想出breakpoint
然后再次按下tab会联想出子命令:

(lldb) breakpoint 
Available completions:
clear
command
delete
disable
enable
list
modify
name
read
set
write
(lldb) breakpoint 

help

查看帮助,支持help b查看b命令的帮助:

_regexp-break <filename>:<linenum>
              main.c:12             // Break at line 12 of main.c
_regexp-break <linenum>
              12                    // Break at line 12 of current file
_regexp-break 0x<address>
              0x1234000             // Break at address 0x1234000
_regexp-break <name>
              main                  // Break in 'main' after the prologue
_regexp-break &<name>
              &main                 // Break at first instruction in 'main'
_regexp-break <module>`<name>
              libc.so`malloc        // Break in 'malloc' from 'libc.so'
_regexp-break /<source-regex>/
              /break here/          // Break on source lines in current file
                                    // containing text 'break here'.
'b' is an abbreviation for '_regexp-break'
help breakpoint list //查看breakpoint list的帮助

run/r

执行程序

breakporint 断点

help breakpoint 查看命令
_regexp-break <filename>:<linenum>
              main.c:12             // Break at line 12 of main.c main.c文件的12行

_regexp-break <linenum>
              12                    // Break at line 12 of current file当前文件12行

_regexp-break 0x<address>
              0x1234000             // Break at address 0x1234000  地址断点

_regexp-break <name>
              main                  // Break in 'main' after the prologue   

_regexp-break &<name>
              &main                 // Break at first instruction in 'main'

_regexp-break <module>`<name>
              libc.so`malloc        // Break in 'malloc' from 'libc.so'

_regexp-break /<source-regex>/
              /break here/          // Break on source lines in current file
                                    // containing text 'break here'.

'b' is an abbreviation for '_regexp-break'

删除断点

l/list

查看当前文件代码

看某个函数的代码:直接输入某个函数的名字即可

(lldb) help list
 List relevant source code using one of several shorthand formats.  Expects 'raw' input (see 'help raw-input'.)

Syntax: 
_regexp-list <file>:<line>   // List around specific file/line
_regexp-list <line>          // List current file around specified line
_regexp-list <function-name> // List specified function
_regexp-list 0x<address>     // List around specified address
_regexp-list -[<count>]      // List previous <count> lines
_regexp-list                 // List subsequent lines

如果程序编译的时候是由很多文件组成的,那么就可以使用list 文件名 看其他文件的代码, 以后再执行 list 3 的时候,看的就是你前面设置的文件名的第三行。

c 、n、 s、 finsh

c/continue,继续执行
n/next,单步调试
s/step,进入一个函数
finsh,执行完当前函数

查看变量、跳帧查看变量

使用po或p,po一般用来输出指针指向的那个对象,p一般用来输出基础变量。普通数组两者都可用

(lldb) po result_array

查看所有帧(bt)

(lldb) bt
函数调用栈由连续的栈帧组成。每个栈帧记录一个函数调用的信息,这些信息包括函数参数,函数变量,函数运行地址。
    当程序启动后,栈中只有一个帧,这个帧就是main函数的帧。我们把这个帧叫做初始化帧或者叫做最外层帧。每当一
个函数被调用,一个新帧将被建立,每当一个函数返回时,函数帧将被剔除。如果函数是个递归函数,栈中将有很多帧是
记录同一个函数的。但前执行的函数的帧被称作最深帧,这个帧是现存栈中最近被创建的帧。
    在程序内部,函数栈帧用函数的地址来标记。一个帧由一定字节的内存组成,每个字节都有自己的地址 。每种类型的计
算机有个约定,用一个特殊字节的地址存放函数帧的地址。通常函数帧的地址存放在一个称作帧指针的寄存器中--$fp.
    gdb 为所有存活的栈帧分配一个数字编号,最深帧的编号是0,被它调用的内个帧的编号就是1。这些编号子程序中是不
存在的,只不过时调试的时候被gdb用的。
    关于函数帧的两个指令:
    frame args
    移动到args指定的栈帧中去,并打印选中的栈的信息。args可以时帧编号或者时帧的地址。如果没有args,则打印当前帧的信息。
    select-frame args
    移动到指定的帧中去,不打印信息。

跳帧(frame select)

(lldb) frame select 1

查看当前帧中所有变量的值(frame variable)

(lldb) frame variable

gdb插件

https://github.com/cyrus-and/gdb-dashboard
只在linux下正常使用,mingw等都没过,下图是wsl2

原文地址:https://www.cnblogs.com/feipeng8848/p/14313939.html