调试的本质:确认原则。确认你认为正确的事情确实是正确的。
node
调试的其余原则:
express
从简单工做开始调试。编程
使用自顶向下方法。
windows
使用调试工具肯定段错误的位置。数组
经过发出中断肯定无限循环的位置。
函数
使用二分搜索。工具
调试器暂停的代码行,其实是将要执行的代码行。操作系统
断点类型:断点 监视点 捕获点unix
设置断点的方式:调试
break function 在函数function()入口处(第一行可执行代码)设置断点。
break line_number 在当前活动源文件的line_number处设置断点。对于多行程序,这要么是上次使用list命令查看其内容的文件,要么是包含main()的文件。
break filename:line_number 若是filename不在当前工做目录中,则能够给出相对路径名或者完整路径名
break filename:function 重载函数或者使用同名静态函数的程序可能须要这种形式。
tbreak是设置临时断点,在第一次中断以后会自动删除。
删除、禁用断点的方式:
delete breakpoint_list 删除断点使用数字标识符
delete 删除全部断点
clear 清除gdb将执行的下一个指令处的断点。
clear function、clear filename:function、clear line_number、clear filename:line_number
disable breakpoint_list
enable breakpoint_list
查看断点属性:info breakpoints
标识符(Num):断点的惟一标识符。
类型(Type):断点的类型。
部署(Disp):下次到达断点后,断点上会发生什么事情。有3种,保持(keep),删除(del),禁用(dis)
启用状态(Enb):启用仍是禁用。
地址(Address):这是内存中设置断点的位置。
位置(What):断点所在位置的行号和文件名。
另外还能够查看,断点已经到达多少次。
恢复执行:
step与next单步调试,后面能够接受一个整数参数n,表示执行n行代码。 根据自顶向下调试原则,应该首先使用next
continue恢复程序执行,后面能够接受一个整数参数n,表示gdb忽略下面n个断点。
finish 当单步进入函数,想要跳过函数的剩余部分,可使用finish。
until 执行程序,直到它到达内存地址比当前内存地址更高的机器指令,而不是直到到达源代码中一个更大的行号。可是until确实可以,跳过循环体,到达循环体外的下一行代码。
事实上,until能够接受源代码中的位置做为参数,就像break同样。这样就能够在任何想要暂停的位置暂停程序了。
eg:until 17,until swap, until swapflaw.c:17, until swapflaw.c:swap
条件断点:
break break-args if (condition) 其中break-args是能够传递给break以指定断点位置的任何参数。condition是布尔表达式,括号是可选的。
eg:break 180 if i < 0 && pt == NULL,break myfunc if i % (j + 3) != 0,break test.c:44 if strlen(mystring) == 0
若是在gdb中使用库函数,而该库不是调试符号编译的,那么惟一能在断点条件中使用的返回值类型为int。
能够对正常断点设置条件以将它们转化为条件断点,使用condition break-num expression,取消条件则是condition break-num
断点命令列表:
为了实现遇到一个断点以后,自动执行一些gdb命令,可使用断点命令列表。
commands breakpoint-num
commands
end
breakpoint-num是断点标示符,下一行的commands是任意的命令,end标示输入完毕。
eg:break fibonacci
commands 1
>silent 为了使gdb更安静地触发断点,必须是第一个命令
>printf "fibonacci was passed %d.\n", n gdb的输出命令,与c语言的语法相同
>continue 断点以后继续自动执行
>end
能够将固定命令列表定义为宏,show user能够获得全部宏的列表
define print_and_go
>printf $arg0, $arg1 最多拥有10个参数
>continue
>end
commands 1
>silent
>print_and_go "fibonacci was passed %d\n" n 注意参数没有逗号
>end
gdb能够调用源代码中的函数:
call myfunc()
在断点命令列表中使用,能够避免修改源码,这点很强大,很方便。
监视点:
它没有住在某一行源代码中,而是当表达式改变时,暂停程序执行。监视的变量必须存在且正处在做用域中,不然没法设置监视点,出做用域以后,监视点也会自动删除。
watch var
watch expression
复杂数据类型变量查看:
动态数组 int* x = (int*)malloc(25 * sizeof(int)); 格式为:p *x@25 也能够用强制转换 p (int[25]) *x
结构体 struct node { int val; struct node* left; struct node* right; }; struct node* nsp; 格式为: p *nsp
类 class node { public: static class node* root; int val; class node* left; class node* right; node(int x); static void insert(int x); static void printtree(class node* nptr); }; class node::root = 0; class node* nsp; 格式为: p *nsp
使用ptype能够查看结构体或类的结构,ptype node。
程序崩溃:用编程界的行话说,当某个错误致使程序忽然和异常地中止执行时,程序崩溃。
迄今最多见的致使程序崩溃的缘由是试图在未经容许的状况下访问一个内存单元。硬件会感知这件事,并执行对操做系统的跳转。在unix系列的平台上,操做系统通常会宣布程序致使段错误(seg fault),并中止程序的执行。在windows系统上,对应的术语是通常保护错误(general protection fault)。使用调试器能够记录崩溃调用栈。
核心文件的使用:
gdb -c core.num target
core.num 是崩溃生成的文件 target是执行的程序