linux下C语言开发16,考虑问题要面面俱到

在前面 15 节的介绍中,我们写了不少 linux 中的C语言程序。相信大家也发现了,即使再简单的C语言程序,也是有可能写错的,毕竟人不是机器。

linux 中的程序错误

写C语言程序出的错千奇百怪,有的是手误写错了符号,有的是头脑发热写反了逻辑,甚至有时还会写错数字。语法错误,编译器能够直接指出,对照着修正没有什么难度。逻辑出错的程序才叫人头疼,这类程序能够编译通过,却得不到正确结果,因为没有编译器帮忙,只能由程序员自己去找错误修正。

程序逻辑出错大体可以分为两种:

  • 一是出错时,程序不会退出,可以继续往下执行。例如调用 open 函数打开文件失败,程序不会退出,还能执行程序员设定的错误处理语句,例如打印错误信息等。
  • 一是一旦出错,程序就直接崩溃退出。比如非法操作内存引起的段错误(这种错误在大型项目开发中经常出现),再例如把 0 当作被除数的浮点错误等。

第一种错误可以勉强认为是预料之中的错误。以 open 函数为例,在定义 open 函数时就已经考虑可能会出现的各种情况了:大多数情况下,open 函数能够成功打开文件。但是在权限不足,或者打开方式不正确时,的确会出现 open 函数打开文件失败的情况。

程序员在定义 open 函数时,会尽力将所有可能的情况都纳入考虑,最后看起来好像 open 函数本身就具有处理错误的能力,输入 man 命令查询其手册:

得知 open 函数在成功打开文件时,会返回文件描述符。如果打开文件出错,它就会返回 -1,并且可以根据 errno 查询出错原因。不管 open 函数执行成功还是出错,所有的情况都在考虑中。

不管成功还是出错,open 函数都告诉计算机该如何处理,所以即使出错,程序也不会意外退出。


第二种错误则完全出乎意料之外了。程序员之前没有考虑到这种情况,所以没有告诉计算机该如何处理,死板的计算机自己又懒得思考,所以出现这种错误时,直接草草结束掉程序了事。

例如,程序员不小心让 0 做被除数了:

#include <stdio.h>

int main()
{
    int a = 8/0;
    printf("%d\n", a);
    return 0;
}

这时程序处理不了 8/0 的计算,只好罢工,直接退出:

设计程序要考虑全面

第二种错误的症结往往很隐蔽,要从几万行甚至几十万行代码中找出错误的原因,难度可想而知。所以,程序员在编写代码时,要将所有可能会发生的事情都考虑到,否则就可能会出现第二种错误。

例如下面这个问题:

编写 C语言程序,取 100 个最大值为 10 的随机数 num,打印出 100/num 的值。

这个问题是简单的,很快就能写出程序:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char i, j = 100;

    while(j--){
        i = rand()%10;
        printf("num %d: %d\n", 100-j, 100/i);
    }

    return 0;
}


编译执行,发现程序并没能按照预期的效果运行:

程序只打印了 12 个数就退出了,并且提示“Floating point exception”,这就是因为没有考虑随机值 i 可能等于 0。因为 i 的值是随机的,程序员并不能准确的得到程序出错的时机,如果这个错误隐藏在几十万行代码里,想像一下这个错误的可怕吧。

所以,程序员一定要足够细心,把所有可能的情况都要考虑到。以上代码可以改写为:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char i, j = 100;

    while(j--){
        i = rand()%10;
        if(i)
            printf("num %d: %d\n", 100-j, 100/i);
        else
            printf("num %d: inf\n", 100-j);
    }

    return 0;
}


只有当 i 不为 0 的时候才计算 100/i,i等于0的时候,打印出 inf。这下,程序终于可以正常工作了:

看来,程序员都该是心思缜密的人。

阅读更多:   Linux笔记
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif