Имеет ли значение, где в моей программе я вызываю 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 без вызова atexit() функции, которые идут после этого if-заявление?

Программа все еще вызывает SDL_DestroyWindow() а также SDL_Quit()которые оба в atexit() функции несмотря на atexit() функции, идущие после return 1 в if (game.window == NULL)-заявление?

Насколько я понимаю, C выполняет код сверху вниз, так как бы он знал, чтобы вызывать функции в atexit() в конце, если return 1 бывает раньше?

2 ответа

Решение

Прежде всего, вы не можете уничтожить окно, пока не узнаете, что оно создано, поэтому вызов atexit(3) для регистрации функции уничтожения окна должен быть выполнен после того, как вы знаете, что окно существует. (это после } закрывающая скобка if)

Призыв к atexit(SDL_Quit); может быть сделано после инициализации среды SDL (это происходит после того, как она была правильно инициализирована, поэтому она будет вызываться только для действительно инициализированной среды), но она должна вызываться перед вызовом, чтобы зарегистрировать уничтожение окна SDL, так как atexit(3) заставляет регистрируемые вами функции вызываться в обратном порядке, поэтому он должен сначала разрушить окно, а затем закрыть среду SDL (и не будет смысла вызывать функцию, которая уничтожает окно, когда SDL уже был закрыто).

Кстати, atexit () требует указателей на функции, а не результата вызова функции. Лучше написать

atexit(SDL_Quit);
atexit(SDL_DestroyWindow);

Чем то, что вы написали.

НОТА

Если функциям нужны параметры, лучше написать обертки функций для их вызова с соответствующими параметрами.

Вы правы, он не будет вызывать функции, зарегистрированные с помощью 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;
}

И это не будет печатать "Пока!", поскольку atexit () регистрируется после проверки для i.

Другие вопросы по тегам