实用调试技巧

实用调试技巧

bug:导致计算机不能正常工作的因素

项目——视图——资源管理器

调试:找bug的过程,英语debug

调试的基本步骤

1.发现程序错误的存在

    发现错误的第一人:程序员——代价小

    发现错误的第二人:测试(开发)工程师

        程序发布:

    发现错误的第三人:用户——代价大

2.以隔离,消除等方式定位错误

3.确定错误产生的原因

4.提出纠正错误的解决方法

5.对程序错误进行改正,重新测试

Debug:称为调试版本,它包含调试信息,并且不做任何优化,便于程序员调试程序

Release:称为发布版本,它往往是进行了各种优化,使得代码在大小和运行速度上都是最优,方便用户使用

Debug包含调试信息,且未优化,文件的大小大于Release

test.c  可执行程序

fn—功能辅助键

fn+f1相当于f1本来的功能

fn+esc——锁定fn——相当于fn一直按着——再次按可以解锁

Debug——> Debug版本的可执行程序(可调试) ctrl+fn+f10(笔记本电脑用)或ctrl+f10(台式电脑用)

Release——>Release版本的可执行程序(测试测的版本)

做Release测试时有错要立即截图保存,有些错误按时间出现

int  main()

{

    int  i=0;

    int  arr[10]={1,2,3,4,5,6,7,8,9,10};

    for(i=0;i<=12;i++)

    {

        printf("hehe\n");

        arr[i]=0;

    }

    return  0;

}

debug版本结果,hehe死循环//此时i的地址比arr高

原因:i循环13次后归为0,arr[12]与i指向同一块空间

栈区默认使用:先使用高地址空间,后使用低地址空间(栈空间的使用)

数组随着下标的增长,地址由低向高变化

release版本(需要在return  0;前加上system("pause");)结果,13行hehe//release优化后arr地址比i高

栈空间:

(高地址)

i

arr9

arr8

arr7

arr6

arr5

arr4

arr3

arr2

arr1

arr0

(低地址)

vs2019中arr和i空了两个地址

vc6.0中arr和i是连续的

gcc中arr和i空一个地址

所以这个代码严格依赖环境

调试步骤:

1.环境:Debug

2.学会快捷键   F5启动调试,和F9配合使用(笔记本可能要加fn,没试过)

F9—断点—创建与取消

断点可以设置条件(右击鼠标,选择条件),可以直接进入第x次循环

按F9会出现一个红点,即为断点,再按F5,代码会执行并停在断点处,再次按F5会跳到逻辑上的下一个断点,不是物理上

先按F10进行调试,然后才能看见调试信息

F10逐过程,用来处理一个过程:一个过程可以是一次函数调用或一条语句

F11逐语句,每次只执行一条语句,可以执行逻辑进入函数内部,F11进入函数内部时,不再看后按shift+fn+f11跳出函数,(台式电脑:shift+f11)

为了方便起见,下面同一用台式电脑表示,笔记本电脑加一个fn(适用于需要f1,f2,f3,f4……f12)

ctrl+f5开始执行不调试,shift+f5停止调试

快速复制一行:ctrl+c,快速删除一行:ctrl+x(剪切,和删除一个效果)

ctrl+f(搜索代码)

ctrl+j(跳到相应行数)

调试——窗口——自动窗口——自动添加执行步骤前的一些变量

调试——窗口——局部变量——同上功能类似——范围为当前变量

调试——窗口——内存——输入地址

资源管理器——视图有所有窗口

设置行号——工具——选项——文本编译器——c/c++——行号

看汇编代码——调试——反汇编

调试——调用堆栈——函数的调用逻辑

如何写出好(易于调试)的代码

优秀的代码:

1.代码运行正常

2.bug很少

3.效率高

4.可读性高

5.可维护性高

6.注释清晰

7.文档齐全

常见coding技巧:

1.使用assert(断言)

2.尽量使用const(常属性)

3.养成良好的编码风格

4.添加必要的注释

5.避免编码的陷阱

void  my_strcpy(char*  dest,char*  src)(6/10分)

{

    while(*src!='\0');

    {

        *dest=*src;

        src++;

        dest++;

    }

    *dest=*src;

}

优化1:

void  my_strcpy(char*  dest,char*  src)(7/10分)

{

    while(*dest++=*src++)

    {

        ;

    }

}

优化2:防止传错指针导致系统崩溃

void  my_strcpy(char*  dest,char*  src)(7/10分)

{

    if(dest!=NULL&&src!=NULL)

    {

        while(*dest++=*src++)

        {

            ;

        }

    }

}

优化3:防止崩溃的同时进行报错

#include<assert.h>

void  my_strcpy(char*  dest,char*  src)(8/10分)

{

    assert(dest!=NULL);

//断言:如果不符合条件会报错,并指出错误对象

//断言内是条件判断,为1正常,为0报错

    assert(src!=NULL);

    while(*dest++=*src++)

        {

            ;

        }

}

优化4:(10/10分)

char*  src前加上const

//const为变量赋予常属性

strcpy返回值为目的地起始地址

void改为char*,添加char*  ret=dest;

                              return  ret;

printf("%s\n",arr1);改为printf("%s\n",my_strcpy(arr1,arr2));

int  main()

{

    char  arr1[]="#########";

    char  arr2[]="bit";

    my_strcpy(arr1,arr2);

    printf("%s\n",arr1);

    return  0;

}

关于const

int  main()

{

    const  int  num=0;

    const  int* p=&num;

    *p=20;

//error

//const放在指针变量的左边时,修饰的是*p,也就是说,不能通过p来改变*p(num)的值

//const int* p和int const *p等价

//const放在指针变量的右边时,修饰的是指针变量p本身,此时p不能改变

//const可以同时放在左边和右边

    printf("%d\n",num);

    return  0;

}

const修饰的指针变量,最好也赋值给一个const赋值的指针变量,否则会有一个小报错

const修饰是不能通过指针修改对应空间,不是空间从此不能修改

原因:const修饰的变量不可改变,权限相对较小;当赋值给一个没有const修饰的变量时,变量权限较大。将一个权限大的值赋给一个权限小的值时会报错。

若不加const在int*前则不会报错,num会被改成20

int num=0;前的const就无意义了

拓展思考:const修饰二级指针

常见错误:

编译型错误:直接看错误提示信息(双击)解决

链接型错误:看错误提示信息,主要在代码中找到错误信息的标识符,然后定位问题所在,一般是标识符名(如函数名)不存在或拼写错误

运行时错误:借助调试,逐步定位问题(最难)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值