使用atexit函数进行异常处理_异常 atexit-程序员宅基地

技术标签: C  

按照ISO C的规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用,通常这32个函数被称为终止处理程序,并调用atexit函数来登记这些函数。
   我们通常认为C语言的起始函数是main函数,实质上一个程序的启动函数并不一定是main函数,这个可以采用链接器来设置,但是gcc中默认main就是C语言的入口函数,在main函数启动之前,内核会调用一个特殊的启动例程,这个启动例程从内核中取得命令行参数值和环境变量值,为调用main函数做好准备,因此对应程序而言main函数并不是起始,但是对应C 语言而言,main函数就是入口地址,其他的链接器帮助我们完成,实际上mian函数的执行是使用了exec函数,这是一个函数族,这也是内核执行一个程序的唯一方法,这在进程控制部分将进行分析。
   记得在面试题中有一道关于在main函数退出之后,是否还可以执行程序的问题,这时候就要使用到前面提到的atexit函数。
     #include<stdlib.h>
     int atexit(void(*func)(void));
    其中,atexit的参数是一个函数地址,当调用此函数时无须传递任何参数,该函数也不能返回值,atexit函数称为终止处理程序注册程序,注册完成以后,当函数终止是exit()函数会主动的调用前面注册的各个函数,但是exit函数调用这些函数的顺序于这些函数登记的顺序是相反的,我认为这实质上是参数压栈造成的,参数由于压栈顺序而先入后出。同时如果一个函数被多次登记,那么该函数也将多次的执行。
   我们知道exit是在main函数调用结束以后调用,因此这些函数的执行肯定在main函数之后,这也是上面面试题的解决方法。即采用atexit函数登记相关的执行函数即可。
   在exit函数的介绍中我们知道,exit()和_exit()以及_Exit()函数的本质区别是是否立即进入内核,_exit()以及_Exit()函数都是在调用后立即进入内核,而不会执行一些清理处理,但是exit()则会执行一些清理处理,这也是为什么会存在atexit()函数的原因,因为exit()函数需要执行清理处理,需要执行一系列的操作,这些终止处理函数实际上就是完成各种所谓的清除操作的实际执行体。atexit函数的定义也给了程序员一种运用exit执行一些清除操作的方法,比如有一些程序需要额外的操作,具体的清除操作可以采用这种方法对特殊操作进行清除等。


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

    void func1(void)
    {
            printf("in func1\n");
    }

    void func2(void)
    {
            printf("in func2\n");
    }

    void func3(void)
    {
            printf("in func3\n");
    }

    int main()
    {
            atexit(func3);
            atexit(func2);
            atexit(func1);

            printf("In main\n");

            return 0;
    }
具体的执行结果如下所示:
In main
in func1
in func2
in func3
根据exit的执行过此可知,exit首先会调用各个终止处理程序,然后按需多次调用fclose(),关闭所有打开流,也就是说exit函数会执行一个标准I/O库的清理关闭操作:对所有打开的流调用fclose(),这样就会造成所有缓冲的输出数据都被冲洗即写入文件中。
   内核使程序执行的唯一方法是调用一个exec函数,进程自愿终止哦的唯一方法是显式或者隐式调用(通过exit函数)_exit()或者_Exit()函数。因此exit函数中实质是对_exit()或者_Exit()函数的封装。exit会先执行自定义的终止处理函数,然后执行I/O库函数清理函数fclose(),这也是为什么可以在终止处理函数中可以继续运用printf之类函数的原因,因为I/O库函数的流对象还没有被清除,当然可以继续运用。执行完了所有的fclose()以后,可以执行真正意义上的终止函数_exit()或者_Exit()函数。
使用exit()函数进行异常终止:
#include <stdio.h>
#include <stdlib.h>
void Exception(void)                           //注册终止函数,通过挂接到此函数,捕获异常信息 
{
    printf("试图去除以一个为0的数字,出现异常!\n");
}
int main()
{ 
   double a,b,result;
  printf("请输入第一个数字:");
  scanf("%lf",&a);
  printf("请输入第二个数字:");
  scanf("%lf",&b);
  if(0==b)                    //如果除数为0终止程序 ,并挂接到模拟异常捕获的注册函数
  {
      
  atexit(Exception);                          
  exit(EXIT_FAILURE);
  } 
   result=diva(a,b);
   printf("相除的结果是: %.2lf\n",result);    
return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u012822866/article/details/44541167

智能推荐

vatee万腾前瞻性的科技愿景:Vatee领先的技术创新-程序员宅基地

文章浏览阅读330次,点赞7次,收藏6次。Vatee万腾深信未来的科技将更加智能化,因此公司致力于研发和推动人工智能、机器学习等领域的技术创新。Vatee万腾以其前瞻性的科技愿景和领先的技术创新,正在引领着数字化时代的潮流。通过对未来的深刻洞察和创新力量的释放,Vatee万腾助推着科技发展进入了一个更加激动人心的新阶段。因此,公司在技术创新中注入了更多的人性化设计和个性化定制,以满足不同用户的需求,提供更加贴心的数字化体验。Vatee万腾一直以来都是科技领域的领军者,其前瞻性的科技愿景成为公司引领未来的驱动力。

Docker详解-程序员宅基地

文章浏览阅读3.8w次,点赞25次,收藏139次。Docker详解一、Docker基础1、Docker简介Docker 是一个开源的应用容器引擎,基于Go 语言并遵从 Apache2.0 协议开源。让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互隔离,性能开销极低。Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。2、_docker

多平台支持的RTSP-Server组件EasyRTSPServer如何实现自定义数据传输-程序员宅基地

文章浏览阅读342次。EasyRTSPServer是一套稳定、高效、可靠、多平台支持的RTSP-Server组件,接口调用非常简单成熟,无需关注RTSPServer中关于客户端监听接入、音视频多路复用、RTSP具体流程、RTP打包与发送等相关问题,支持多种音视频格式,再也不用去处理整个RTSP OPTIONS/DESCRIBE/SETUP/PLAY/RTP/RTCP的复杂流程和担心内存释放的问题了,非常适合于安防领域、...

用拓扑排序检测有向图中是否有环_拓扑排序判断有向图是否有环-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏15次。目录算法主要步骤代码测试数据提示:由于拓扑排序的检测方式不涉及到边权或点权,所以拓扑序列中的正环和负环都能够被检测出来。检测可达负环可以用Bellman-Ford或者SPFA。算法主要步骤1. 记录每个结点的入度,设置一个队列,专门存放入度为0的结点,设置一个整型计数变量inqNum,记录加入过队列的结点的个数。2. 首先将所有的入度为0的点放入队列中,进入while循环,条件是队列不为空,对于队列中的每一个点,都对齐后继结点的入度进行减一操作,如果在那之后该后继节点的入度变为0_拓扑排序判断有向图是否有环

58同城辉少许《乡村振兴战略下传统村落文化旅游设计》许少辉七一新书-程序员宅基地

文章浏览阅读108次。58同城辉少许《乡村振兴战略下传统村落文化旅游设计》许少辉七一新书。58同城辉少许《乡村振兴战略下传统村落文化旅游设计》许少辉七一新书。

SylixOS 系统 MQTT中间件移植-程序员宅基地

文章浏览阅读396次。SylixOS对开源MQTT的移植测试

随便推点

PCDViewer的常用操作-程序员宅基地

文章浏览阅读4.5k次,点赞3次,收藏23次。PCDViewer是一款功能强大但操作极为简单的点云可视化和编辑软件,支持对点云的渲染显示、查询、量测、建图拼接、编辑、格式转换等功能,同时支持了pose文件、矢量文件等的显示。PCDViewer目前提供了Windows、Ubuntu18.04、Ubuntu20.04等版本。本页面总结了PCDViewer的基本、常用操作。在安装目录下,双击PCDViewer,或者通过命令行打开PCDViewer,即可启动软件。软件支持pcd、ply、las点云文件的打开。_pcdviewer

SpringCloud Gateway 新网关与zuul的对比选型_springcloud zuul和gateway对比-程序员宅基地

文章浏览阅读7.4k次,点赞4次,收藏13次。SpringCloud Gateway是Spring Cloud的一个全新项目, 基纡Spring 5.0+ Spring Boot 2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统- -的 API路由管理方式。SpringCloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以..._springcloud zuul和gateway对比

Electron入门 01:快速入门_electron教程-程序员宅基地

文章浏览阅读9k次,点赞14次,收藏58次。文章目录目的总结目的总结_electron教程

【GRU回归预测】灰狼算法优化注意力机制卷积神经网络结合门控循环单元GWO-Attention-CNN-GRU数据预测(多维输入单输出)【含Matlab源码 3732期】-程序员宅基地

文章浏览阅读327次,点赞6次,收藏11次。灰狼算法优化注意力机制卷积神经网络结合门控循环单元GWO-Attention-CNN-GRU数据预测(多维输入单输出)完整的代码,方可运行;可提供运行操作视频!适合小白!

SQLite源程序分析之sqlite3.c-程序员宅基地

文章浏览阅读437次。/******************************************************************************** This file is an amalgamation of many separate C source files from SQLite** version 3.14.1. By combining al...

一文读懂Python中的异常处理-程序员宅基地

文章浏览阅读1k次。异常处理在任何一门编程语言里都是值得关注的一个话题,良好的异常处理可以让你的程序更加健壮,清晰的错误信息更能帮助你快速修复问题。在Python中,和不部分高级语言一样,使用了try/except/finally语句块来处理异常,如果你有其他编程语言的经验,实践起来并不难。异常处理语句 try...excpet...finally实例代码defdiv(a, b):try:print(a / b)ex...

推荐文章

热门文章

相关标签