在我的程序中调用 atexit() 的位置是否重要?

Does it matter where in my program I call atexit()?

基本上,我正在用 SDL 编写程序。

这是部分代码:

    // create game window
    game.window = SDL_CreateWindow(
        "Game",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        160,
        144,
        0
    );

    if (game.window == NULL)
    {
        fprintf(stderr, "Window error: %s\n", SDL_GetError());
        return 1;
    }

    atexit(SDL_DestroyWindow());
    atexit(SDL_Quit());
    return 0;
}

我的问题如下。考虑到 C 的程序性质,如果 (game.window == NULL) 是这种情况并且 return 1 执行会发生什么。程序是否以 return 1 终止而不调用此 if 语句之后的 atexit() 函数?

程序是否仍然调用 SDL_DestroyWindow()SDL_Quit(),它们都在 atexit() 函数中,尽管 atexit() 函数在 return 1 之后if (game.window == NULL)-语句?

据我了解,C是从上到下执行代码的,那么如果return 1之前发生,它怎么知道最后调用atexit()中的函数?

你是对的,它不会调用那些用atexit()注册的函数。

为了展示这种行为,我写了一个小代码片段。

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

void bye()
{
        printf("Bye!\n");
}

int main(int argc, char *argv[])
{
        int i = 1;
        if (i) {
                printf("Ending\n");
                return 0;
        }
        atexit(bye);
        return 0;
}

这不会打印 "Bye!",因为 atexit() 在检查 .

首先,你不能销毁window 在你确实知道你已经创建它之前所以调用atexit(3) 注册函数以销毁 window 必须在 知道 window 存在 之后完成。 (这是在 if} 右括号之后)

atexit(SDL_Quit); 的调用可能会在您初始化 SDL 环境后完成(这是在它被正确初始化之后,因此它只会在真正初始化的环境中被调用)但它必须被调用before 调用注册销毁 SDL window,因为 atexit(3) 使您注册的函数被调用以相反的顺序,因此它必须首先销毁 window,然后关闭 SDL 环境(当 SDL 已经关闭时,调用销毁 window 的函数是没有意义的)。

顺便说一下,atexit() 需要函数指针,而不是函数调用的结果。最好写

atexit(SDL_Quit);
atexit(SDL_DestroyWindow);

比你写的要好。

注意

如果函数需要参数,最好编写函数包装器以使用适当的参数调用它们。