C语言中的程序终止函数
在C语言的标准库<stdlib.h>中提供了一些与正常或者不正常的程序终止有关的函数,下面分别对其进行简单介绍。
参考文献:
[1] C和指针,P298,342
[2] C程序设计语言现代方法(第2版),P489
1 abort()
abort()函数用于不正常地终止一个正在执行的程序。函数原型如下:
void abort(void)
这个函数将引发SIGABRT信号,你可以在程序中为这个信号设置一个信号处理函数,在程序终止(或干脆不终止)之前采取任何你想采取的动作,甚至可以不终止程序。
abort()函数类似于exit()函数,但调用它会导致异常的程序终止。atexit()函数注册的退出函数不会被调用。根据具体的实现,它可能不会清理包含未输出数据的输出缓冲区,不会关闭打开的流,也不会删除临时文件。abort()函数返回一个由实现定义的状态码来指出“不成功的终止”。
补充:
调用abort()函数时,实际上会产生SIGABRT信号。如果没有处理SIGABRT信号的函数,那么程序会如前所述那样异常终止。如果(通过调用signal()函数)为SIGABRT安装了信号处理函数,那么就会调用处理函数。如果处理函数返回,随后程序会异常终止。但是,如果处理函数不返回(比如它调用了longjmp()函数),那么程序就不会终止。
2 atexit()
atexit()函数可以把一些函数注册为退出函数(exit function)。函数原型如下:
int atexit(void (*func) (void))
把函数指针传递给atexit()函数时,它会把指针保存起来留给将来引用。当程序将要正常终止时(或者由于调用exit,或者由于main函数返回),退出函数将被调用。退出函数不能接受任何参数。
3 exit()
exit()函数用于正常终止程序。函数原型如下:
void exit(int)
如果程序以main函数返回一个值结束,那么其效果相当于用这个值作为参数调用exit()函数。在程序中的任何位置执行exit(n)调用通常等价于在main函数中执行return n。
int参数返回给操作系统,用于提示程序是否正常完成。预定义符号EXIT_SUCCESS和EXIT_FAILURE分别提示程序的终止成功还是失败。exit()函数仅有的另一个可移植参数是0,它和宏EXIT_SUCCESS的意义相同。虽然程序也可以使用其他值,但它们的具体含义将取决于编译器。
当程序发现错误情况使它无法继续执行下去时,这个函数尤其有用。你经常会在调用perrno之后再调用exit()终止程序。尽管终止程序并非处理所有错误的正确方法,但和一个注定失败的程序继续执行以后再失败相比,这种做法更好一些。
注意,这个函数没有返回值。当exit()函数结束时,程序已经消失,所以它无处返回。
当exit()函数被调用时,所有被atexit()函数注册为退出函数的函数将按照它们所注册的顺序被反序依次调用(参数由于被压入栈中,而先进后出)。然后,所有用于流的缓冲区被刷新,所有打开的文件被关闭。用tmpfile()函数创建的文件被删除。然后,退出状态返回给宿主环境,程序停止执行。
警告:
由于程序停止执行,所以exit()函数绝对不会返回到它的调用处。但是,如果任何一个用atexit()注册为退出函数的函数如果再次调用了exit(),其效果是未定义的。这个错误可能导致一个无限循环,很可能只有当堆栈的内存耗尽才会终止。
4 _exit()
_exit()函数类似于exit()函数,但是_exit()不会调用atexit()注册的退出函数,也不会调用之前传递给signal()函数的信号处理函数。此外,_exit()函数不需要清洗输出缓冲区,关闭打开的流,以及删除临时文件,是否执行这些操作是由实现定义的。函数原型如下:
void _exit(int)
按照ISO C规定,一个进程可以登记多达32个函数,通常这32个函数被称为终止处理程序(退出函数),通过调用atexit()函数来登记这些函数,这些函数将由exit()函数自动调用。
exit()和_exit()以及_Exit()函数的本质区别是是否立即进入内核,_exit()以及_Exit()函数都是在调用后立即进入内核,而不会执行一些清理处理,但是exit()则会执行一些清理处理,这也是为什么会存在atexit()函数的原因,因为exit()函数需要执行清理处理,需要执行一系列的操作,这些终止处理函数实际上就是完成各种所谓的清除操作的实际执行体。atexit函数的定义也给了程序员一种运用exit执行一些清除操作的方法,比如有一些程序需要额外的操作,具体的清除操作可以采用这种方法对特殊操作进行清除等。
内核使程序执行的唯一方法是调用一个exec()函数,进程自愿终止的唯一方法是显式或者隐式调用(通过exit函数)_exit()或者_Exit()函数。因此exit函数中实质是对_exit()或者_Exit()函数的封装。exit会先执行自定义的终止处理函数,然后执行I/O库函数清理函数fclose(),这也是为什么可以在终止处理函数中可以继续运用printf之类函数的原因,因为I/O库函数的流对象还没有被清除,当然可以继续运用。执行完了所有的fclose()以后,可以执行真正意义上的终止函数_exit()或者_Exit()函数。
C语言中的程序终止函数的更多相关文章
- C语言中可变参数的函数(三个点,“...”)
C语言中可变参数的函数(三个点,“...”) 本文主要介绍va_start和va_end的使用及原理. 在以前的一篇帖子Format MessageBox 详解中曾使用到va_start和va_end ...
- C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .
我们在C语言编程中会遇到一些参数个数可变的函数,一般人对它的实现不理解.例如Printf(): Printf()函数是C语言中非常常用的一个典型的变参数函数,它 的原型为: int printf( c ...
- C语言中变量名及函数名的命名规则与驼峰命名法
一.C语言变量名的命名规则:(可以字母,数字,下划线混合使用) 1. 只能以字母或下划线开始:2. 不能以数字开始:3. 一般小写:4. 关键字不允许用(eg:int float=2//error ...
- C++基础 (8) 第八天 数组指针 模板指针 C语言中的多态 模板函数
1昨日回顾 2 多态的练习-圆的图形 3多态的练习-程序员薪资 4员工管理案例-抽象类和技术员工的实现 employee.h: employee.cpp: technician.h: technici ...
- c语言中不允许在函数外部给全局变量赋值
今天,在写条件编译的时候,出现了在函数外部给全局变量赋值的情况,gcc报错,那么c语言为什么不允许在函数外部给变量赋值呢?为什么声明变量的时候可以对变量进行赋值? 出错代码: /* 2 * ===== ...
- 简答的理解C语言中的各种类型函数
1.变参函数 变长参数的函数即参数个数可变.参数类型不定 的函数.最常见的例子是printf函数.scanf函数和高级语言的Format函数.在C/C++中,为了通知编译器函数的参数个数和类型可变(即 ...
- C语言中生产随机数 rand()函数
参考资料:C语言中产生随机数 一:如果你只要产生随机数而不需要设定范围的话,你只要用rand()就可以了:rand()会返回一随机数值, 范围在0至RAND_MAX 间.RAND_MAX定义在stdl ...
- javascript语言中的一等公民-函数
简介 在很多传统语言(C/C++/Java/C#等)中,函数都是作为一个二等公民存在,你只能用语言的关键字声明一个函数然后调用它,如果需要把函数作为参数传给另一个函数,或是赋值给一个本地变量,又或是作 ...
- C语言中内存的申请函数
C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等. alloca是向栈申请内存,因此无需释放. malloc分配的内存是位于堆中的,并且 ...
随机推荐
- Remove “System Program Problem Detected” Messages From Ubuntu
One of my Ubuntu systems would pop up the following message multiple times after logging in: System ...
- js原生瀑布流
背景: 1.在移动端开发,jq文件是显得非常庞大的,所以所有效果尽量用HTML5和原生js实现. 2.本次瀑布流是固定列数,采用非浮动的另外一种瀑布流思想实现的. 3.本次数据来源是json接口 4. ...
- tcp_tw_recycle和tcp_timestamps的文章汇总
临近年关,人会变得浮躁,期间写的代码可谓乱七八糟.不过出来混始终是要还的,这不最近就发现一个PHP脚本时常连不上服务器. 遇到这类问题,我习惯于先用strace命令跟踪了一下看看: shell ...
- careercup-中等难度 17.5
17.5 写一个函数来模拟游戏. 游戏规则如下: 4个槽,里面放4个球,球的颜色有4种,红(R ),黄(Y),绿(G),蓝(B).比如, 给出一个排列RGGB,表示第一个槽放红色球,第二和第三个槽放绿 ...
- UNIX标准化及实现之基本系统数据类型
历史上,某些UNIX系统变量已与某些C数据类型联系在一起.例如,历史上主.次设备号一直存放在一个16位的短整型中,8位表示主设备号,另外8位表示次设备号.但是,很多较大的系统需要用多于256个值来表示 ...
- WordPress搭建Personal Blog
早就想搭建一个专属于自己的博客了,用来记录自己生活.学习的点点滴滴.之所以选WordPress,主要是因为它可以支持Latex,而且特别喜欢其简约的风格. WordPress有个the famous ...
- ajax检查用户名
Ajax实现的效果 究竟Ajax能实现什么功能呢?今天下午学习了一下Ajax,现在跟大家分享一下我的学习心得.Ajax是什么?工作机制又是什么?可能不大准确,只是我个人看了视频学习后的一点点看法. A ...
- mvc ajax_返回数据
假设cshtml文件中是这样的: <script type="text/javascript"> $(document).ready(function(){ $(&qu ...
- 西门子PLC两线制,四线制
1 一.对于控制系统模块:两线制,四线制信号都只有两根线接入模件,区别在于: 两线制信号的这两根线一正一负,不带提供信号电流,而且提供供电电压:一般流量,压力,液位等等的信号常用两线制信号,但也要根据 ...
- IE兼容低版本
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><m ...