c++调试技巧

看书的时候,结合自己不足一年的编程经验,写出来的一个还算是比较基础的c++调试经验的总结。

1、重现bug
要重现bug,首先采用与bug第一次出现时完全相同的输入。注意不要只执行触发操作,因为bug 可能是由整个操作序列产生的。

当能一致地重现这个bug时,应尝试找出触发这个bug的最小序列代码,可以从仅包含触发操作的最小序列开始,然后慢慢扩大至覆盖启动时的完整序列代码,直到bug被触发时。–> 这会得到重现这个bug的最简单高效的测试用例。

2、调可重复的bug

目标是找到触发这个问题的准确的代码行。
1)记录调试信息,通过观察调试信息来判断bug出现的地点。不过若手边有一个现成的调试器,不建议加上调试信息,因为调试信息的修改与还原比较麻烦
2)直接使用调试器来进行调试,附上gdb的调试的一篇转文。(此处已经默认读者可以熟练使用调试器的基本操作)

3、调不可重复的bug

这种bug的调试非常困难,因为很难重现bug出现时的情景(只能使用自己的经验进行大胆的猜测)。。。所以调试这种bug,手边没有什么特别厉害的调试工具时,只能够通过检查代码来发现问题,不过有趣的时,这种方法时时也竟会比较有效。因为我们带着刚才发生bug的视角再来重新审视一遍代码时,往往会有很大可能发现出问题所在。
不过,我们在这里并不建议长时间盯着代码看而是手工跟踪代码的执行路径

4、调试内存问题。
不要解除对nullptr指针的引用。
一般的内存错误的检查:
1)确保每一个new的调用都匹配了一个delete的调用。同样,每一个对malloc、alloc和calloc的调用都要匹配一个对free的调用。每一个new[]的调用也要匹配一个对delete[]的调用。为了避免双重释放内存或使用已释放的内存,建议释放内存后将指针设置为空
2)检查缓冲区的溢出,每次迭代访问一个数组或者读写一个c风格的字符串的时候,验证没有越过数组尾部访问的内存。通过使用STL容器和字符串通常可以避免此类问题
3)检查无效指针的解除引用
4)在堆栈上声明指针的时候,一定要确保在声明中初始化指针,如:

T* p = nullptr;
//或 T* p = new T;
//不要 T* p;

5)同样,确保总是在类的构造函数中初始化指针数据成员,既可以在构造函数中分配内存也可以将指针设置为nullptr。

(ps:内存错误并不总是会立刻出现,它有可能是程序中各个代码段综合作用的结果,往往需要调试器和一点耐心才可以。)

你可能感兴趣的:(C++,bug)