Aller au contenu

Guide RAII en C

Ce document décrit l'utilisation du pattern RAII (Resource Acquisition Is Initialization) en C via les attributs GCC/Clang.

Mécanisme : __attribute__((cleanup))

GCC et Clang supportent l'attribut cleanup qui appelle automatiquement une fonction de nettoyage lorsqu'une variable sort de portée :

// Déclaration du destructeur
static void cleanup_timer(HybridTimer** t) {
    if (*t) hybrid_timer_stop(*t);
}

// Utilisation avec RAII
void ma_fonction(void) {
    HybridTimer* timer __attribute__((cleanup(cleanup_timer))) =
        hybrid_timer_start("Ma Fonction");

    // ... code ...

} // ← timer est automatiquement stoppé ici, même en cas de return anticipé

Macros RAII du projet

HYBRID_FUNC_TIMER

Mesure le temps d'exécution d'une fonction CPU complète :

void render_frame(App* app) {
    HYBRID_FUNC_TIMER; // ← Démarre un chrono, stoppé automatiquement en fin de fonction

    // ... rendu ...
}

GPU_STAGE_PROFILER

Encapsule une passe de rendu GPU avec les timestamps GL :

void render_skybox(App* app) {
    GPU_STAGE_PROFILER(&app->gpu_profiler, "Skybox Pass", COLOR_CYAN);
    // ← Timestamps début/fin automatiques

    glDrawArrays(GL_TRIANGLES, 0, 3);
}

RAII_SATISFY_*

Macros pour satisfaire l'analyse statique dans les patterns RAII :

// Indique à clang-tidy que le pointeur est géré par RAII
Resource* res RAII_SATISFY_CLEANUP = resource_create();

Ces macros évitent les faux positifs de type « ressource non libérée » dans les analyseurs statiques.

Exemple complet : Gestion de fichiers

// Destructeur pour FILE*
static void cleanup_file(FILE** f) {
    if (*f) { fclose(*f); *f = NULL; }
}

// Usage
bool process_config(const char* path) {
    FILE* f __attribute__((cleanup(cleanup_file))) = fopen(path, "r");
    if (!f) return false;

    // ... traitement ...

    return true;
    // ← fclose() appelé automatiquement, même ici
}

Cas d'utilisation dans le projet

Macro Type de ressource Durée de vie
HYBRID_FUNC_TIMER Chronomètre CPU Durée de la fonction
GPU_STAGE_PROFILER Requête timer GL Portée du bloc {}
RAII_BUFFER_MAP Mapping de tampon GL Portée du bloc {}
RAII_DEBUG_GROUP glPushDebugGroup Portée du bloc {}

Portabilité

L'attribut cleanup est supporté par : - GCC 4.0+ - Clang 3.0+ - ARM Compiler 5.06+

Non supporté sur MSVC (compilation Windows via MinGW utilise GCC/Clang, donc compatible).

Voir aussi