常用的调试技巧(如何检测bug)(二)

简介: 常用的调试技巧(如何检测bug)

4.多多动手,尝试调试,才能有进步。


一定要熟练掌握调试技巧。


初学者可能80%的时间在写代码,20%的时间在调试。


但是一个程序员可能20%的时间在写 程序,但是80%的时间在调试。


我们所讲的都是一些简单的调试。


以后可能会出现很复杂调试场景:多线程程序的调试等。 多多使用快捷键,提升效率


5. 一些调试的实例


5.1 实例一 实现代码:

求 1!+2!+3! ...+ n! ;不考虑溢出。

#imclude<stdio.h>
int main()
{
 int i = 0;
 int sum = 0;//保存最终结果
 int n = 0;
 int ret = 1;//保存n的阶乘
 scanf("%d", &n);
 for(i=1; i<=n; i++)
 {
 int j = 0;
 for(j=1; j<=i; j++)
 {
 ret *= j;
 }
 sum += ret;
 }
 printf("%d\n", sum);
 return 0;
}

这时候我们如果3,期待输出9,但实际输出的是15。

why?

这里我们就得找我们问题。

1. 首先推测问题出现的原因。初步确定问题可能的原因最好。

2. 实际上手调试很有必要。

3. 调试的时候我们心里有数。

5.2 实例二

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[10] = {0};
    for(i=0; i<=12; i++)
   {
        arr[i] = 0;
        printf("hehe\n");
   }
    return 0;
}

研究程序死循环的原因。


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


6.1 优秀的代码:

1. 代码运行正常


2. bug很少


3. 效率高


4. 可读性高


5. 可维护性高


6. 注释清晰


7. 文档齐全


常见的coding技巧:


1. 使用assert


2. 尽量使用const


3. 养成良好的编码风格


4. 添加必要的注释


5. 避免编码的陷阱。


6.2 示范:

模拟实现库函数:strcpy

/***
*char *strcpy(dst, src) - copy one string over another
*
*Purpose:
*       Copies the string src into the spot specified by
*       dest; assumes enough room.
*
*Entry:
*       char * dst - string over which "src" is to be copied
*       const char * src - string to be copied over "dst"
*
*Exit:
*       The address of "dst"
*
*Exceptions:
*******************************************************************************/
char * strcpy(char * dst, const char * src)
{
        char * cp = dst;
 assert(dst && src);
        while( *cp++ = *src++ )
               ;     /* Copy src over dst */
        return( dst );
}

注意:


1. 分析参数的设计(命名,类型),返回值类型的设计


2. 这里讲解野指针,空指针的危害。


3. assert的使用,这里介绍assert的作用


4. 参数部分 const 的使用,这里讲解const修饰指针的作用


5. 注释的添加


6.3 const的作用  

#include <stdio.h>
//代码1
void test1()
{
    int n = 10;
    int m = 20;
    int *p = &n;
    *p = 20;//ok?
    p = &m; //ok?
}
void test2()
{
     //代码2
    int n = 10;
    int m = 20;
    const int* p = &n;
    *p = 20;//ok?
    p = &m; //ok?
}
void test3()
{
    int n = 10;
    int m = 20;
    int *const p = &n;
    *p = 20; //ok?
    p = &m;  //ok?
}
int main()
{
    //测试无cosnt的
   test1();
    //测试const放在*的左边
    test2();
    //测试const放在*的右边
    test3();
    return 0;
}

结论:


const修饰指针变量的时候:


1. const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改 变。但是指针变量本身的内容可变。


2. const如果放在*的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指 针指向的内容,可以通过指针改变。


7. 编程常见的错误


7.1 编译型错误

直接看错误提示信息(双击),解决问题。或者凭借经验就可以搞定。相对来说简单。


7.2 链接型错误

看错误提示信息,主要在代码中找到错误信息中的标识符,然后定位问题所在。一般是标识符名不 存在或者拼写错误


7.3 运行时错误

借助调试,逐步定位问题。最难搞。


温馨提示: 做一个有心人,积累排错经验。


讲解重点: 介绍每种错误怎么产生,出现之后如何解决。


相关文章
|
传感器 安全 API
SCP Firmware入门一篇就够啦
SCP Firmware入门一篇就够啦
1038 0
|
10月前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
195 69
|
安全 Ubuntu 测试技术
l4re Getting started
l4re Getting started
616 0
|
存储 Linux Apache
释放磁盘空间:解决文件删除但空间未释放的困扰
在管理Linux系统的日常中,最令人头疼的时刻之一就是发现尽管已删除了巨大的文件,但是磁盘空间的占用率仍然没有任何下降。这种情况不仅让我怀疑自己的操作是否正确,同时也给操作系统的运行带来了隐患。 究竟问题出在哪,又该如何解决?本次记录,将演示释放磁盘空间:解决文件删除但空间未释放的困扰。
释放磁盘空间:解决文件删除但空间未释放的困扰
|
jenkins Java 测试技术
Jenkins 在持续集成/持续交付(CI/CD)管道中的应用
【8月更文第31天】 在现代软件开发过程中,持续集成(Continuous Integration, CI)和持续交付(Continuous Delivery, CD)已经成为提升开发效率和软件质量的重要实践。Jenkins 是一个广泛使用的开源工具,它能够帮助团队实现自动化构建、测试和部署,是 CI/CD 流水线的核心组件之一。本文将详细介绍 Jenkins 在 CI/CD 管道中的应用,并提供具体的代码示例。
473 0
|
Kubernetes Cloud Native Docker
什么是容器:从基础到进阶的全面介绍
什么是容器:从基础到进阶的全面介绍
2659 1
|
消息中间件 Linux
Linux进程间通信(IPC)教程 Linux共享内存介绍:介绍POSIX共享内存的基本概念、用途和编程实践
Linux进程间通信(IPC)教程 Linux共享内存介绍:介绍POSIX共享内存的基本概念、用途和编程实践
351 2
|
Android开发 开发者 UED
使用AlarmManager实现Android应用中的定时任务
使用AlarmManager实现Android应用中的定时任务
|
Linux 编译器 测试技术
探索Linux设备树:硬件描述与驱动程序的桥梁
探索Linux设备树:硬件描述与驱动程序的桥梁
1222 0