设为首页 加入收藏

TOP

嵌入式系统C编程之错误处理(六)
2015-01-22 20:57:58 来源: 作者: 【 】 浏览:44
Tags:嵌入式 系统 编程 错误 处理
决于实现。Unix系统中_Exit 和_exit同义,两者均直接进入内核,而不冲洗标准I/O流。_exit函数由exit调用,处理Unix特定的细节。
?
? ? ?exit()函数首先调用执行各终止处理程序,然后按需多次调用fclose函数关闭所有已打开的标准I/O流(将所有缓冲的输出数据冲洗写到文件上),然后调用_exit函数进入内核。
?
? ? ?标准函数库中有一种“缓冲I/O(buffered I/O)”机制。该机制对于每个打开的文件,在内存中维护一片缓冲区。每次读文件时会连续读出若干条记录,下次读文件时就可直接从内存缓冲区中读取;每次写文件时也仅仅写入内存缓冲区,等满足一定条件(如缓冲区填满,或遇到换行符等特定字符)时再将缓冲区内容一次性写入文件。通过尽可能减少read和write调用的次数,该机制可显著提高文件读写速度,但也给编程带来某些麻烦。例如,向文件内写入一些数据时,若未满足特定条件,数据会暂存在缓冲区内。开发者并不知晓这点,而调用_exit()函数直接关闭进程,导致缓冲区数据丢失。因此,若要保证数据完整性,必须调用exit()函数,或在调用_exit()函数前先通过fflush()函数将缓冲区内容写入指定的文件。
?
? ? ?例如,调用printf函数(遇到换行符'\n'时自动读出缓冲区中内容)函数后再调用exit:
?
复制代码
1 int main(void)
2 {
3 ? ? printf("Using exit...\n");
4 ? ? printf("This is the content in buffer");
5 ? ? exit(0);
6 ? ? printf("This line will never be reached\n");
7 }
复制代码
? ? ?执行输出为:
?
1 Using exit...
2 This is the content in buffer(结尾无换行符)
? ? ?调用printf函数后再调用_exit:
?
复制代码
1 int main(void)
2 {
3 ? ? printf("Using _exit...\n");
4 ? ? printf("This is the content in buffer");
5 ? ? fprintf(stdout, "Standard output stream");
6 ? ? fprintf(stderr, "Standard error stream");
7 ? ? //fflush(stdout);
8 ? ? _exit(0);
9 }
复制代码
? ? ?执行输出为:
?
1 Using _exit...
2 Standard error stream(结尾无换行符)
? ? ?若取消fflush句注释,则执行输出为:
?
1 Using _exit...
2 Standard error streamThis is the content in bufferStandard output stream(结尾无换行符)
? ? ?通常,标准错误是不带缓冲的,打开至终端设备的流(如标准输入和标准输出)是行缓冲的(遇换行符则执行I/O操作);其他所有流则是全缓冲的(填满标准I/O缓冲区后才执行I/O操作)。
?
? ? ?三个exit函数都带有一个整型参数status,称之为终止状态(或退出状态)。该参数取值通常为两个宏,即EXIT_SUCCESS(0)和EXIT_FAILURE(1)。大多数Unix shell都可检查进程的终止状态。若(a)调用这些函数时不带终止状态,或(b)main函数执行了无返回值的return语句,或(c) main函数未声明返回类型为整型,则该进程的终止状态未定义。但若main函数的返回类型为整型,且执行到最后一条语句时返回(隐式返回),则该进程的终止状态为0。
?
? ? ?exit系列函数是最简单直接的错误处理方式,但程序出错终止时无法捕获异常信息。ISO C规定一个进程可以登记32个终止处理函数。这些函数可编写为自定义的清理代码,将由exit()函数自动调用,并可使用atexit()函数进行登记。
?
#include
?
int atexit(void (*func)(void));
?
? ? ?该函数的参数是一个无参数无返回值的终止处理函数。exit()函数按登记的相反顺序调用这些函数。同一函数若登记多次,则被调用多次。即使不调用exit函数,程序退出时也会执行atexit登记的函数。
?
? ? ?通过结合exit()和atexit()函数,可在程序出错终止时抛出异常信息。以除零错误为例:
?
复制代码
double Division(double fDividend, double fDivisor)
{
? ? return fDividend/fDivisor;
}
void RaiseException1(void)
{
? ? printf("Exception is raised: \n");
}
void RaiseException2(void)
{
? ? printf("The divisor cannot be 0!\n");
}
?
int main(void)
{
? ? double fDividend = 0.0, fDivisor = 0.0;
? ? printf("Enter the dividend: ");
? ? scanf("%lf", &fDividend);
? ? printf("Enter the divisor : ");
? ? scanf("%lf", &fDivisor);
? ? if(0 == fDivisor)
? ? {
? ? ? ? atexit(RaiseException2);
? ? ? ? atexit(RaiseException1);
? ? ? ? exit(EXIT_FAILURE);
? ? }
? ? printf("The quotient is %.2lf\n", Division(fDividend, fDivisor));
?
? ? return 0;
}
复制代码
? ? ?执行结果为:
?
1 Enter the dividend: 10
2 Enter the divisor : 0
3 Exception is raised:?
4 The divisor cannot be 0!
? ? ?abort()函数原型声明如下:
?
#include
?
void abort(void);
?
? ? ?该函数将SIGABRT信号发送给调用进程(进程不应忽略此信号)。
?
? ? ?ISO C规定,调用abort将向主机环境递送一个未成功终止的通知,其方法是调用raise(SIGABRT)函数。因此,abort()函数理论上的实现为:
?
1 void abort(void)
2 {
3 ? ? raise(SIGABRT);
4 ? ? exit(EXIT_FAILURE);
5 }
? ? ?可见,即使捕捉到SIGABRT信号
首页 上一页 3 4 5 6 7 8 下一页 尾页 6/8/8
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Objective-C中的继承和多态 下一篇objective-c 复制对象

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: