当前位置: 首页 > news >正文

(C语言) stdlib 程序终止

文章目录

  • 💣前言
  • 💣程序终止
    • 🧨EXIT_SUCCESS & EXIT_FAILURE
    • 🧨_Exit (C99)
    • 🧨exit & atexit
      • 🧨🧨exit
      • 🧨🧨atexit
    • 🧨quick_exit & at_quick_exit (C11)
      • 🧨🧨quick_exit
      • 🧨🧨at_quick_exit
    • 🧨abort
  • ⭐END
    • 🌟关注我

💣前言

<stdlib.h> 是一个非常非常重要的库。重要到没有他就没有程序。

但由于太重要了,且涉及过多底层相关内容,一半初学不会强调这些内容。升值一些工作了一段时间在 CRUD 的程序员也不太了解。

本文重点整理C语言中在 stdlib 下有关 程序终止 相关的接口。

顺便回答大家一个一直关心的问题:

如果 main函数 不写return 0;会怎样?

main 函数返回时,无论是通过 return 语句还是抵达函数尾,都会将 return 语句的实参(或若使用隐式返回,则为 0)作为 exit_code 传递并执行 exit()

特别注意:笔者在 windowsmingw 测试 quick_exit & at_quick_exit 编译失败,linux 下编译成功。

💣程序终止

🧨EXIT_SUCCESS & EXIT_FAILURE

EXIT_SUCCESS, EXIT_FAILURE - cppreference.com

EXIT_SUCCESSEXIT_FAILURE 宏展开成能用作 exit 的实参的整数表达式(从而作为从 main 函数返回的值),并指示程序执行状态。

常见实现

// 实现决定
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

注意:EXIT_SUCCESS 和值0都能指示程序执行成功的状态,尽管并不要求 EXIT_SUCCESS 等于0。

main 函数,若正常结束,默认等效于 return 0;

🧨_Exit (C99)

_Exit - cppreference.com

在 C++11 中加入 C++ 标准

导致发生程序正常终止,但不完全清理资源

void              _Exit(int exit_code);  // (C99 起) (C11 前)
_Noreturn void    _Exit(int exit_code);  // (C11 起) (C23 前)
[[noreturn]] void _Exit(int exit_code);  // (C23 起)
  • 不调用传递给 at_quick_exit()atexit() 的函数。
  • 实现定义:是否将未写入数据冲入打开的流、关闭打开的流或移除临时文件。

exit_code的值:

  • 为 0 或 EXIT_SUCCESS:则将指示成功终止的状态返回给宿主环境。
  • EXIT_FAILURE:则返回指示不成功终止的实现定义状态。
  • 其他:即实现定义

🧨exit & atexit

🧨🧨exit

exit - cppreference.com

导致发生正常程序终止。

void              exit(int exit_code);  // (C11 前)
_Noreturn void    exit(int exit_code);  // (C11 起) (C23 前)
[[noreturn]] void exit(int exit_code);  // (C23 起)

进行几个清理步骤:

  • 以注册的逆序调用传递给 atexit 的函数
  • 冲入并关闭所有 C 流
  • 移除 tmpfile 创建的文件
  • 控制返回给宿主环境。若 exit_code 为零或 EXIT_SUCCESS,则返回指示成功终止的实现定义状态。若 exit_code 为 EXIT_FAILURE,则返回指示不成功终止的实现定义状态。其他情况下返回实现定义的状态值。

下面操作是未定义行为

  • 若程序调用 exit 多于一次
  • 同时有调用 exitquick_exit
  • 在调用由 atexit 注册的函数期间,以 longjmp 退出该函数

🧨🧨atexit

atexit - cppreference.com

int atexit(void (*func)(void));

注册 func 所指向的函数,使它在程序正常终止(通过 exit() 或从 main() 返回)时得到调用。

  • 逆序调用注册成功的函数。
  • 可以注册同一函数多于一次。
  • 实现保证支持注册至少 32 个函数。确切的极限是由实现定义的。
  • 若注册成功则为 0,否则为非零值。

示例code

#include <stdio.h>
#include <stdlib.h>void fun1(void) {puts("atexit fun1");
}void fun2(void) {puts("atexit fun2");
}int main(void) {atexit(fun1);atexit(fun2);FILE *fp = fopen("data.txt", "r");if (fp == NULL) {fprintf(stderr, "error opening file data.txt in function main()\n");exit(EXIT_FAILURE);} else {fclose(fp);}printf("Normal Return\n");return EXIT_SUCCESS;
}

在没有 data.txt 的情况下,输出:

error opening file data.txt in function main()
atexit fun2
atexit fun1

有 data.txt 的情况下,输出:

Normal Return
atexit fun2
atexit fun1

🧨quick_exit & at_quick_exit (C11)

🧨🧨quick_exit

quick_exit - cppreference.com

在 C++11 中加入 C++ 标准

导致程序正常终止,而不完全清理资源

_Noreturn void    quick_exit(int exit_code);  // (C11 起) (C23 前)
[[noreturn]] void quick_exit(int exit_code);  // (C23 起)

效果流程:

  • 以注册顺序的逆序调用传递给 at_quick_exit的函数。
  • 调用 _Exit(exit_code)

说白了就是不做额外处理的 exit()

🧨🧨at_quick_exit

at_quick_exit - cppreference.com

在 C++11 中加入 C++ 标准

注册 func 所指向的函数,使它在程序正常终止(通过 quick_exit ())时得到调用。

int at_quick_exit(void (*func)(void));  //(C11 起)s
  • at_quick_exit 线程安全,从多个线程调用此函数不会导入数据竞争。

  • 逆序调用注册成功的函数。

  • 实现保证支持注册至少 32 个函数。确切的极限是由实现定义。

  • 若注册成功则为 0,否则为非零值。

  • 所注册的函数在程序正常终止时并不会被调用

🧨abort

abort - cppreference.com

导致程序异常终止,除非传递给 signal 的信号处理函数正在捕捉 SIGABRT 且该处理函数不返回。

void              abort(void);  // (C11 前)
_Noreturn void    abort(void);  // (C11 起) (C23 前)
[[noreturn]] void abort(void);  // (C23 起)
  • 不调用传递给 atexit()的函数。
  • 实现定义:是否关闭打开的资源。
  • 向宿主环境返回指示不成功执行实现定义状态

POSIX 指定 abort() 函数撤除阻塞,或忽略 SIGABRT 信号。

某些编译器内建子程序:

  • __builtin_trap(gcc、clang 及 icc)
  • __fastfail/__debugbreak(msvc)

能用于尽可能快地终止程序。

示例code

#include <stdio.h>
#include <stdlib.h>void fun_1(void) {puts("atexit fun1");
}
void fun_q1(void) {puts("at_quick_exit fun1");
}
int main(void) {atexit(fun_1);at_quick_exit(fun_q1);puts("Before abort()");abort();puts("After abort()");printf("Normal Return\n");
}

执行效果

Before abort()
Aborted



⭐END

🌟关注我

⭐交流方式⭐ |C/C++|算法|设计模式|软件架构-CSDN社区

关注我,学习更多C/C++,算法,计算机知识

B站:

👨‍💻主页:天赐细莲 bilibili





http://www.mrgr.cn/news/12116.html

相关文章:

  • 搭建面向切面编程项目
  • QT常用UI控件
  • 说一说业务架构和应用架构
  • 利用命令模式实现一个手游后端架构的方法总结
  • 分享32位单片机测亩仪方案
  • Kubernetes存储Volume
  • 利用session.upload_progress执行文件包含
  • 虚幻5|按键触发学习
  • sqli-labs靶场通关攻略(36-40关)
  • 命题的相关知识
  • matplotlib保存指定图像大小
  • uni-app开发日志:schema2code生成的新增页和修改页因字段太多用分段器实现分段分类
  • VS环境中使用QT、OpenCV进行简易图像处理(附源码)
  • DBSCAN算法详解
  • Vulkan入门系列18 - 计算着色器(Compute Shader)
  • Linux(CentOS8)系统安装mysql-8.0.26-linux-glibc2.12-x86_64.tar.xz
  • fastapi知识点及应用
  • pyautogui的一些自动化示例,附代码
  • 计算机毕业设计选题推荐-OA办公管理系统-Java/Python项目实战
  • 金融涉案账户压降行动的实施成效与挑战