【问题标题】:Three questions about atexit关于atexit的三个问题
【发布时间】:2018-04-13 13:08:25
【问题描述】:

返回值:

   The atexit() function returns the value 0 if successful; otherwise, it returns a nonzero value.

示例:

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

void
bye(void)
{
    printf("That was all, folks\n");
}

int
main(void)
{
    long a;
    int i;

    a = sysconf(_SC_ATEXIT_MAX);
    printf("ATEXIT_MAX = %ld\n", a);

    i = atexit(bye);
    if (i != 0) {
        fprintf(stderr, "cannot set exit function\n");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

我已经阅读了手册页和 StackOverflow 问题,但仍有三个关于 atexit 的问题:

  1. atexit 什么时候会失败,所以它会返回非零值?请给我这样的演示,谢谢!
  2. 正如我们所知,bye 在调用 exit() 之前不会被调用。那么这是否意味着在调用 exit() 之前我们无法知道atexit 的返回值?如果是,那么第三个问题:
  3. 既然已经调用了exit(),那么if表达式怎么执行?

【问题讨论】:

  • atexit 不需要能够存储无限数量的函数指针,因此如果内存不足,它可能会返回错误代码。
  • “我已阅读手册页和 StackOverflow 问题” - 恭喜。你已经是前 1% 的开发者了!
  • atexit 只是注册一个函数作为退出处理程序的一部分调用。它的返回值是注册是否成功;不是它注册的函数的返回值; atexit 不会调用已注册的函数;当程序退出时(通常)会调用它们。

标签: c++ c exit atexit


【解决方案1】:

我们知道,bye 在 exit() 被调用之前不会被调用。那么这是否意味着在调用 exit() 之前我们无法知道atexit 的返回值?

我不确定我是否能完全按照您的想法进行,但误解似乎如下:

atexit() 报告成功只是意味着“我接受了你给我的任何指针,它指向的函数将在退出时调用”。这并不意味着对您的函数的实际调用会成功。

atexit() 报告错误因此意味着:“无论出于何种原因,我无法接受您的指针”。您的运行时环境可能内存不足,无法存储另一个指针或类似的东西。

【讨论】:

    【解决方案2】:

    atexit() 注册了一个在程序退出时调用的函数,但它完成了它的执行并将控制权返回给调用上下文,而无需等待程序终止。换句话说,它不会暂停程序执行,如果不是为了注册传递的函数的时间。然后程序将从调用atexit() 的位置恢复,并且只有当它因任何原因终止时,才会调用注册的处理程序。

    这应该回答您的问题 2:atexit()“立即”返回一个值,而不是在程序终止时。这也应该回答了你的问题3:调用atexit()时不会调用exit(),程序流程可以正常继续。

    关于您的第一个问题,atexit() 可能失败的条件取决于特定的 libc 实现。在这些情况下,将返回一个负值,errno 将包含一个反映错误情况的代码。例如,在 GNU libc ate​​xit() 中,如果它无法为传递的错误函数分配条目,则返回错误,请参阅 __new_exitfn() source code,由 atexit (source code here) 内部调用。

    【讨论】:

      【解决方案3】:

      atexit 函数只是将函数添加到“列表”中。它本身不会调用您传递指针的函数。它也不会等待exit 被调用,因为这将使它变得毫无用处。因此它可以立即返回(带有可能的错误代码),程序继续正常运行。

      如果函数未能将您传递给其内部“列表”的函数指针添加到其内部“列表”(例如,它可能是有限的大小,并且您尝试添加更多),那么它将返回失败。同样,它会立即返回,而不是等待 exit 调用。

      【讨论】:

        【解决方案4】:

        关于问题 1:atexit 仅设置一个函数在退出时调用。只要它能够设置该函数,它就会返回 0,而不管该函数是否实际被调用过。

        这样就回答了您的问题 2 和 3:不,您不需要等待 exit() 知道 atexit 的返回,因此评估 if 也没有问题。

        【讨论】:

          猜你喜欢
          • 2012-12-25
          • 2011-02-19
          • 2018-07-27
          • 1970-01-01
          • 1970-01-01
          • 2021-08-14
          • 2023-03-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多