Linux下编译工具主要是gcc,所以这里调试主要学习gcc(也可以用cc/g++)的编译。
常用调试步骤:
测试:找出程序存在的缺陷或错误
固化:让程序错误可重现
定位:确定相关代码行
纠正:修改代码错误
验证:确定问题解决了
启动gdb只需在gcc的时候,后面加个-g表示调试的符号,比如“gcc -g -o test test.c”,执行gdb test就进入调试了。enter键是执行上一个命令,在step和next时很有用。
gdb 生成的object文件名 即可进入调试。
list可显示10行程序,list后面加数字表示从第几行开始显示;
run命令执行该程序,,可简写为r;
break命令可以增加断点,后面加数字代表行号;
print可以用来显示参数值,简写p,如果参数或结果是sum,可以使用print sum显示此时sum值的大小;
step表示分步执行,可简写为s,会进入函数;
continue继续执行程序,简写c;
next就是单条语句执行,可简写为n,不会进入函数;
backstace,即bs,查看函数堆栈;
在调试的时候还可以打补丁,就是修改调试里面的程序,比如想修改参数sum为0,可以通过命令set variablesum=0,接下来调试的时候sum的初始值就变成0了;
调试的时候还可以通过info命令查看一些信息,比如查看我设置的断点在哪里,命令info break就显示出来了,同样,通过disable命令可以使断点失效;delete删除断点;clear为清除所有断点;
finish可以退出函数;
until运行命令直到退出循环体,u;
断言:
有的时候在程序中调用断言库“assert.h”可以起到很好的效果,而该函数也比较简单,void assert(int expression),assert宏对表达式进行求值,结果非零的话就会在标准错误写诊断信息,然后调用abort结束程序。
后记:
关于gcc和clang编译器的比较。
clang编译器运行比gcc快点,原因是gcc编译器执行的任务比较全,不仅检查词法和语法分析,而且要实现代码优化和机器代码生成的任务。而clang只需要完成语法、词法分析,代码优化和生成机器代码交给LLVM完成。另外clang代码提示比较友好,可以显示更加精确的错误位置。
总的来说,gcc是一个单一的可执行程序编译器,其内部完成了从预处理到代码生成的全部过程,但其中间过程无法被其他程序调用。clang出现的时间比gcc晚,她是为了更好的“专注一件事”而设计的。不过有的程序gcc跑没问题,可clang会莫名的报错……