gdb调试c++:
参考
gdb Debugger Tutorial Series – thisPointer
https://users.ece.utexas.edu/~adnan/gdb-refcard.pdf
# g++编译选项
# g++
g++ main.cpp -o main -H # 打印出编译过程中使用的所有头文件
g++ a.cc b.cc -o main. # multi file
## 查看汇编源码
g++ -c main.cpp # generate main.o
objdump -d main.o # dump
g++ -S main.cpp # main.s,也是一个二进制文件
gcc -E main.cpp # 查看预处理之后的文件
gcc -E main.cpp -o log # 查看main.cpp进行头文件和宏展开之后的代码,棒
# 如何使用gdb模式
# c++
g++ -g main.cpp -o main # 使用-g编译一个debug的编译文件main
# g++ 其他编译选项:g++ -Wall -Werror -Weffc++
gdb main # 运行编译文件
# python and c++
gdb --args python main.py # gdb只能调试c++语句,对于pthon语句可以使用pdb。
gdb --args executablename arg1 arg2 arg3 # executablename是可执行程序 args是传参
# gdb语法
# 运行整个程序
run
# 设置断点
break main.cpp:10 # 在main.cpp第10行设置断点
# 直接输入break回车会在当前行打断点
# 运行程序到下一个断点c=continute
c
c 10 # 对当前断点直接跳过运行10次之后
# 运行程序到下一行n=next
n
# 重复运行上一次的语句比如再次运行到下一行可以不在输入n,直接按回车就会默认执行上一次执行的命令
# 当运行到某一个行时是一个函数,如果运行n则会到下一行,若果希望进入这个函数查看,可以用s命令来debug到这个函数里。
s
# 退出debug, q=quit
q
# 查看所有断点
info break
# 删除某个断点
d 1 # 这里删除第一个断点,断点有Num属性,从1开始
d # 删除所有的断点
# 查看backtrace,即运行到当前断点时所有运行过的函数,感觉时最有用的工具之一了。
bt
f 3 # 程序进入到bt中的第三个进程里
up # 切换到下一个进程
set scheduler-locking on # 只调试当前线程
finish # 结束当前函数的gdb调试,有的时候会进入一个确认没问题的函数,可以直接finish结束然后进到下一个函数中继续查看
ptype var # 打印var的类型
whatis var # 查看var类型
disas # 查看反汇编函数
i r # 查看registers
# 使用gdb文本页面
gdb -tui main
# 或者gdb之后ctrl + x + a打开tui页面
# 显示某个变量的变换
# auto a = weight.quantized_scale() # 假设想跟踪a的变化
break XXX:num # 先打断点到下一行
display a # 显示a
# 1: a = 18.6296
c # 继续运行程序就可以
undisplay 1 # remove display
gdb可以和pdb一起用
# 配置~/.gdbinit
set print thread-events off # 关闭没用的Threads Events显示
set overload-resolution off # 解决cannot resolve method XXX to any overloaded instance问题
set confirm off # 退出时不显示信息
c++出现undefined symbol: _ZN9torch_mlu4XXX
可以使用: c++filt _ZN9torch_mlu4XXX
这个命令可以显示出哪个地方没有定义。
# no such file or directory,在gdb模式下输入
dir path/to/your/workspace
或者把上面一行加到~/.gdbinit里
汇编相关语法(参考wiki)
rax - register a extended
rbx - register b extended
rcx - register c extended
rdx - register d extended
rbp - register base pointer (start of stack)
rsp - register stack pointer (current location in stack, growing downwards)
rsi - register source index (source for data copies)
rdi - register destination index (destination for data copies)
add %r10,%r11 // add r10 and r11, put result in r11
add $5,%r10 // add 5 to r10, put result in r10
call label // call a subroutine / function / procedure
cmp %r10,%r11 // compare register r10 with register r11. The comparison sets flags in the processor status register which affect conditional jumps.
cmp $99,%r11 // compare the number 99 with register r11. The comparison sets flags in the processor status register which affect conditional jumps.
div %r10 // divide rax by the given register (r10), places quotient into rax and remainder into rdx (rdx must be zero before this instruction)
inc %r10 // increment r10
jmp label // jump to label
je label // jump to label if equal
jne label // jump to label if not equal
jl label // jump to label if less
jg label // jump to label if greater
mov %r10,%r11 // move data from r10 to r11
mov $99,%r10 // put the immediate value 99 into r10
mov %r10,(%r11) // move data from r10 to address pointed to by r11
mov (%r10),%r11 // move data from address pointed to by r10 to r10
mul %r10 // multiplies rax by r10, places result in rax and overflow in rdx
push %r10 // push r10 onto the stack
pop %r10 // pop r10 off the stack
ret // routine from subroutine (counterpart to call)
syscall // invoke a syscall (in 32-bit mode, use "int $0x80" instead)