目录
1. 源文件
test.cpp
#include <iostream>
int main(int argc,char**argv)
{
int itest = 100;
const char *str = "this is a test";
std::cout << "itest is " << itest << " str is " << str << std::endl;
std::cout << "param is " << std::endl;
for ( int i = 0; i < argc;i++)
{
std::cout << argv[i] << std::endl;
}
std::cout << "hello world \n";
return 0;
}
Makefile
EXE:=section1
EXECUTABLE:= $(EXE)
LIBDIR:=
LIBS:=
INCLUDES:=.
SRCDIR:=
CC:=g++
#CFLAGS:= -g -Wall -o0
CPPFLAGS:= -g
CPPFLAGS+= $(addprefix -I,$(INCLUDES))
CPPFLAGS+= -I.
CPPFLAGS+= -MMD
RM-F:= rm -f
SRCS:= $(wildcard *.cpp) $(wildcard $(addsuffix /*.cpp,$(SRCDIR)))
OBJS:= $(patsubst %.cpp,%.o,$(SRCS))
DEPS:= $(patsubst %.o,%.d,$(OBJS))
MISSING_DEPS:= $(filter-out $(wildcard $(DEPS)),$(DEPS))
.PHONY : all deps objs clean
all:$(EXECUTABLE)
deps:$(DEPS)
objs:$(OBJS)
clean:
@$(RM-F) *.o
@$(RM-F) *.d
@$(RM-F) $(EXE)
ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS):
@$(RM-F) $(patsubst %.d,%.o,$@)
endif
-include $(DEPS)
$(EXECUTABLE) : $(OBJS)
$(CC) -o $(EXECUTABLE) $(OBJS) $(addprefix -L,$(LIBDIR)) $(addprefix -l,$(LIBS))
2. 编译
注意 在 makefile中一定加入 -g 编译标志符,用于生成调试信息。
3.GDB 调试 ![](https://i-blog.csdnimg.cn/blog_migrate/a9635870f5393141c4fcf7501f8155f7.png)
4. 常用调试指令总结
quit:
退出 gdb
list: 缩写l
列出周围的源程序 或列出函数源程序
命令控制程序的运行
run(缩写r)
运行程序
break(缩写b)
打断点
next(缩写n)
下一步
print(缩写p)
显示具体内容
- x 按十六进制格式显示变量。
- d 按十进制格式显示变量。
- u 按十六进制格式显示无符号整型。
- o 按八进制格式显示变量。
- t 按二进制格式显示变量。
- a 按十六进制格式显示变量。
- c 按字符格式显示变量。
- f 按浮点数格式显示变量。
set args
可指定运行时参数,如:set args 10 20 ;
show args
命令可以查看设置好的运行参数。
path <dir>
可设定程序的运行路径;
set environment varname [=value]
用于设置环境变量,如set env USER=agm;
show environment [varname]
则用于查看环境变量。
gdb中也可以使用重定向控制程序输出,如
run > tmpfile;
step <count>
单步跟踪,如果有函数调用,则进入该函数(进入函数的前提是,此函数被编译有debug信息)。step后面不加count表示一条条地执行,加表示执行后面的count条指令,然后再停住。
next <count>
单步跟踪,如果有函数调用,它不会进入该函数。同样地,next后面不加count表示一条条地执行,加表示执行后面的count条指令,然后再停住
watch命令
观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序
r如下 i变化后,程序打印信息并挺住
examine命令(缩写为x)
查看内存地址中的值 x/<n/f/u> <addr>
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容;f 表示显示的格式,如果地址所指的是字符串,那么格式可以是s,如果地址是指令地址,那么格式可以是i;u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4字节。u参数可以被一些字符代替:b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指定的内存地址开始,读写指定字节,并把其当作一个值取出来。n、f、u这3个参数可以一起使用,例如命令“x/3uh 0x54320”表示从内存地址0x54320开始以双字节为1个单位(h)、16进制方式(u)显示3个单位(3)的内存。
set命令
修改寄存器,修改内存
set {unsigned int}0x800100101=0x0
jump命令
jump <linespec>
修改程序的执行顺序,从而让程序随意跳跃
signal命令
signal <signal>
产生一个信号量给被调试的程序, 如 "ctrl+c" 信号
return命令
return <expression>
使用return命令强制函数忽略还没有执行的语句并返回
call命令
call <expr>
强制调用某函数
info命令
查看寄存器、断点、观察点和信号等信息
info registers (查看除了浮点寄存器以外的寄存器)
info all-registers (查看所有寄存器,包括浮点寄存器)
info registers <regname ...> (查看所指定的寄存器)
info break 列出当前所设置的所有观察点
info watchpoints 查看有哪些信号正在被GDB检测,
info signals info handle 也可以使用info line命令来查看源代码在内存中的地址。
info threads可以看多线程。
info line后面可以跟行号、函数名、文件名:行号、文件名:函数名等多种形式
set scheduler-locking off|on|step 命令
off 不锁定任何线程,也就是所有线程都执行,这是默认值。
on 只有当前被调试程序会执行。
step 在单步的时候,除了next过一个函数的情况以外,只有当前线程会执行。
与多线程调试相关的命令还包括:
thread ID切换当前调试的线程为指定ID的线程。
break thread_test.c:123 thread all 在所有线程中相应的行上设置断点
thread apply ID1 ID2 command 让一个或者多个线程执行GDB命令command。
thread apply all command让所有被调试线程执行GDB命令command。
disassemble 命令
用于反汇编,它可被用来查看当前执行时的源代码的机器码,其实际上只是把目前内存中的指令dump出来