exit, atexit și EXIT_SUCCESS în C

Oprește programul din orice funcție, cu un cod de ieșire; atexit înregistrează funcții de rulat la final.

Sintaxă
#include <stdlib.h>
[[noreturn]] void exit(int cod);
int atexit(void (*functie)(void));
#define EXIT_SUCCESS 0
#define EXIT_FAILURE /* de obicei 1 */

Ce face exit, atexit și EXIT_SUCCESS

exit(cod) termină programul imediat, chiar dacă ești adânc într-o funcție. Înainte de oprire, apelează funcțiile înregistrate cu atexit (în ordine inversă înregistrării), golește bufferele fișierelor deschise și le închide. return cod; din main are același efect.

Codul de ieșire este citit de sistem sau de scriptul care a pornit programul (echo $? în terminal). EXIT_SUCCESS (0) înseamnă succes, EXIT_FAILURE înseamnă eroare.

atexit este util pentru curățenie: ștergerea fișierelor temporare sau scrierea unui mesaj de final, oriunde s-ar opri programul. Există și quick_exit și _Exit, care opresc programul fără aceste etape.

Parametri

Parametru Descriere
cod Codul de ieșire: EXIT_SUCCESS, EXIT_FAILURE sau un număr între 0 și 255.
functie La atexit: o funcție fără parametri și fără valoare returnată.

Ce returnează

exit nu se întoarce. atexit întoarce 0 dacă înregistrarea a reușit.

Exemple

Exemplul 1: Funcții rulate la final cu atexit

Funcțiile se apelează în ordine inversă: ultima înregistrată rulează prima.

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

static void inchide_jurnal(void) { printf("Jurnal închis\n"); }
static void salveaza(void) { printf("Date salvate\n"); }

int main(void) {
    atexit(inchide_jurnal);
    atexit(salveaza);
    printf("Programul lucrează...\n");
    exit(EXIT_SUCCESS);
}

Rezultat

Programul lucrează...
Date salvate
Jurnal închis

Exemplul 2: Oprire cu eroare dintr-o funcție

Fișierul nu există, deci programul afișează mesajul și se oprește cu codul 1. Linia de după apelul funcției nu mai rulează.

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

static FILE *deschide_sau_iesi(const char *cale) {
    FILE *f = fopen(cale, "r");
    if (f == NULL) {
        fprintf(stderr, "Nu pot deschide %s\n", cale);
        exit(EXIT_FAILURE);
    }
    return f;
}

int main(void) {
    FILE *f = deschide_sau_iesi("note.txt");
    printf("Fișier deschis\n");
    fclose(f);
    return EXIT_SUCCESS;
}

Ieșire în terminal

$ ./program; echo "cod de ieșire: $?"
Nu pot deschide note.txt
cod de ieșire: 1

Greșeli frecvente

  • Apelezi exit într-o funcție de bibliotecă: cine o folosește nu mai poate trata eroarea. Întoarce un cod de eroare și lasă main să decidă.
  • Crezi că exit eliberează memoria alocată cu malloc în locul tău. Sistemul de operare o recuperează la oprire, dar instrumentele de verificare (Valgrind, sanitizere) o raportează ca neeliberată.
  • Folosești coduri peste 255 sau negative: sistemul păstrează doar ultimii 8 biți, deci exit(256) apare ca 0.

Comenzi înrudite

  • main: Funcția cu care începe orice program C: sistemul o apelează la pornire, iar valoarea returnată spune dacă programul a reușit.
  • assert: Verifică în timpul rulării o condiție care trebuie să fie mereu adevărată și oprește programul cu un mesaj dacă nu este.
  • errno, perror și strerror: errno păstrează codul ultimei erori a unei funcții de bibliotecă; perror și strerror îl transformă într-un mesaj citibil.
  • fopen și fclose: Deschide un fișier pentru citire, scriere sau adăugare și returnează un FILE *; fclose îl închide și salvează datele rămase.