int main(int argc, char **argv) int main(int argc, char **argv)
{ {
/* здесь код */ /* здесь код */
return 0; /* ?? Что возвращает main()? */
} }
Стандарт С 1999 г. указывает, что при выпадении в конце, поведение функции main()
void
— плохая мысль, которая может вести лишь к ошибочному коду.)Возвращенное из main()
wait()
и waitpid()
».ЗАМЕЧАНИЕ
. На системах GNU/Linux управляемая компилятором команда c99 запускает компилятор с соответствующими опциями, так что возвращаемое значение при выпадении из конца функции равно 0. Простой gcc этого не делает.9.1.5.3. Функции завершения
Другим способом естественного завершения программы является вызов функций завершения. Стандарт С определяет следующие функции:
#include
void exit(int status);
void _Exit(int status);
int atexit(void (*function)(void));
Эти функции работают следующим образом:
void exit(int status)
Эта функция завершает программу, status
exit()
вызывает все функции, зарегистрированные с помощью atexit()
, сбрасывает на диск и закрывает все открытые потоки <stdio.h> FILE
* и удаляет все временные файлы, созданные tmpfile()
(см. раздел 12.3.2 «Создание и открытие временных файлов»). Когда процесс завершается, ядро закрывает любые оставшиеся открытыми файлы (которые были открыты посредством open()
, creat()
или через наследование дескрипторов), освобождает его адресное пространство и освобождает любые другие ресурсы, которые он мог использовать. exit()
никогда не возвращается.void _Exit(int status)
Эта функция в сущности идентична функции POSIX _exit()
int atexit(void (*function)(void))
function
exit()
запускает функцию обратного вызова перед закрытием файлов и завершением. Идея в том, что приложение может предоставить одну или более функций очистки, которые должны быть запущены перед окончательным завершением работы. Предоставление функции называется ее nftw()
обсуждались в разделе 8.4.3.2 «Функция обратного вызова nftw()
»; здесь та же идея, хотя atexit()
вызывает каждую зарегистрированную функцию лишь однажды.)atexit()
errno
.Следующая программа не делает полезной работы, но демонстрирует, как работает atexit()
/* ch09-atexit.c --- демонстрация atexit().
Проверка ошибок для краткости опущена. */
/*
* Функции обратного вызова здесь просто отвечают на вызов.
* В настоящем приложении они делали бы больше. */
void callback1(void) { printf("callback1 called\n"); }
void callback2(void) { printf("callback2 called\n"); }
void callback3(void) { printf("callback3 called\n"); }
/* main --- регистрация функций и завершение */
int main(int argc, char **argv) {
printf("registering callback1\n"); atexit(callback1);