Variables globales en Rust : mythes, réalité et alternatives sécurisées

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : "Où sont les variables globales ?" — le premier choc du débutant en Rust

\n\n

Vous venez de commencer à apprendre Rust, vous avez écrit quelques programmes, et soudain vous réalisez : vous avez besoin qu'une variable soit accessible depuis n'importe quel point du code. En Python ou JavaScript, vous écririez simplement global_var = 42 au niveau supérieur — et c'est fait. Mais en Rust... le compilateur vous regarde d'un air réprobateur et affiche une erreur.

\n\n

La question "Is it possible to use global variables in Rust?" est l'une des plus populaires sur Stack Overflow. Et ce n'est pas sans raison. Rust, contrairement à de nombreux langages, ne permet pas de déclarer une variable globale simplement. Pourquoi ? Parce que la sécurité mémoire n'est pas qu'un mot à la mode, c'est le fondement du langage.

\n\n

Dans cet article, nous analyserons toutes les méthodes pour travailler avec des données globales en Rust : des simples constantes aux stockages thread-safe. Vous apprendrez à contourner les limitations du compilateur sans sacrifier la sécurité, et quand les variables globales sont un mal nécessaire ou une nécessité.

\n\n

Pourquoi Rust interdit-il les variables globales "normales" ?

\n\n

Avant de chercher des solutions, comprenons le problème. Rust applique des règles strictes de possession (ownership) et d'emprunt (borrowing). Une variable globale qui peut être modifiée depuis n'importe quel thread à tout moment est une voie directe vers une course aux données (data race).

\n\n

Imaginez : deux threads tentent simultanément d'écrire des valeurs différentes dans la même variable globale. Le résultat est imprévisible. En C++ ou C, cela conduit à un comportement indéfini. Rust garantit qu'un tel code ne compilera tout simplement pas.

\n\n

C'est pourquoi le compilateur exige que nous spécifiions explicitement :

\n
    \n
  • La variable est immuable ? Utilisez const ou static.
  • \n
  • La variable est mutable et utilisée dans un seul thread ? Utilisez static mut (avec unsafe).
  • \n
  • La variable est mutable et utilisée dans plusieurs threads ? Utilisez Mutex, RwLock ou des types atomiques.
  • \n
\n\n

Méthode 1 : Les constantes (const) — l'option la plus sûre

\n\n

Si votre "valeur globale" est en réalité une constante qui ne change jamais, utilisez const :

\n\n
const MAX_CONNECTIONS: u32 = 100;\nconst DATABASE_URL: &str = "postgresql://localhost:5432/mydb";\n\nfn main() {\n    println!("Maximum de connexions : {}", MAX_CONNECTIONS);\n}
\n\n

Les constantes en Rust ne sont pas de simples variables. Elles sont inlinées par le compilateur à l'endroit de leur utilisation. C'est-à-dire qu'à la compilation, MAX_CONNECTIONS sera remplacée par le nombre 100. C'est efficace, mais cela signifie que la constante n'a pas d'adresse mémoire fixe. Si vous avez besoin d'un emplacement mémoire (par exemple pour FFI), utilisez static.

\n\n

Méthode 2 : Les variables statiques (static)

\n\n

Si vous avez besoin d'une variable globale avec une adresse mémoire fixe, utilisez static :

\n\n
static APP_NAME: &str = "My Rust Application";\nstatic VERSION: u32 = 1;\n\nfn main() {\n    println!("Lancement de {} version {}", APP_NAME, VERSION);\n}
\n\n

Par défaut, les variables static sont immuables. Cela garantit la sécurité dans un environnement multithread. Mais que faire si vous devez modifier un état global ?

\n\n

Méthode 3 : Les variables statiques mutables (static mut) — attention, unsafe !

\n\n

Rust permet de déclarer une variable statique mutable avec static mut. Mais il y a un piège : toute lecture ou écriture de cette variable nécessite un bloc unsafe.

\n\n
static mut COUNTER: u32 = 0;\n\nfn increment() {\n    unsafe {\n        COUNTER += 1;\n    }\n}\n\nfn main() {\n    increment();\n    unsafe {\n        println!("Compteur : {}", COUNTER);\n    }\n}
\n\n

Important :

Blogs

Book Recommendations