(三十二)单步调试技术
2018-11-08 本文已影响3人
RGiskard
编译错误与运行错误
-
编译错误:编译器提示的错误,低级错误,语法有错,根本无法生成exe文件
-
运行错误:程序运行的结果与预期不一致,说明程序不对,存在bug,需要修改
一般情况下,能复现的错误都是可以解决的
单步调试
单步调试就是在要调试的代码段首行加断点,走一步看一下结果,边走边观察,直到发现有哪一步走错了
在vs环境下,断点F9,单步F10,(F10是逐过程stepover,跳过函数具体执行,F11是逐语句stepinto,可以进入函数)开始调试F5,再按F5跳到下一个断点,若无下一个断点则退出调试。黄色箭头表示即将执行这条语句
//求和
#include<stdio.h>
int sum(int* buf,int n)
{
int total = 0;
for(int i=0;i<total;i++)
{
total+=buf[i];
}
return total;
}
int main()
{
int buf[64];
for(int i=0;i<64;i++)
{
buf[i]=i;
}
int result = sum(buf,64);
printf("%d\n",result);
return 0;
}
程序结果是零,说明程序有错。利用单步调试发现sum函数写错了
监视窗口可以单独只查看某个变量的情况。内存窗口输入p可以看到指针p对应的内存,观看变量a的内存时输入&a。a=0x12345678对应的内存为78 56 34 12共四个字节。
程序崩溃的原因分类
-
一个变量未初化、未赋值,就读取它的值。( 这属于逻辑问题,往往是粗心大意的导致的 )
-
函数栈溢出(1)定义了一个体积太大的局部变量(2)函数嵌套调用,层次过深(如无穷递归)
int buf[1024*1024*16]; //这个变量体积太大,应该用malloc或new来动态分配内存
//无穷的递归调用 #include <stdio.h> #include <stdlib.h> void a(); void b(); void a() { printf("Calling a() ...\n"); b(); } void b() { printf("Calling b() ...\n"); a(); } int main() { a(); return 0; }
-
数组越界访问
-
指针的目标对象不可用,为空指针,野指针(指针未赋值,已经free/delete了却还要用,不恰当的指针强制转换要求)
//野指针:不恰当的强制转换
#include <stdio.h>
int main()
{
int a = 10;
double* p = (double*) &a;
*p = 123.345; // 程序崩溃
return 0;
}