ProgramaciónDesarrollador de Sistemas/backend y Embebido

Hable sobre las reglas para trabajar con variables globales (static) en Rust. ¿Cómo se asegura la seguridad en el acceso simultáneo y cuáles son las diferencias en los diferentes métodos de inicialización y sincronización?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

En Rust, las variables globales se declaran utilizando la palabra clave static. Estas variables viven durante toda la ejecución del programa. Por defecto, el acceso a static inmutable es seguro, pero para static mutables se requiere usar unsafe, ya que el compilador no puede garantizar la ausencia de condiciones de carrera.

Para el acceso seguro a las variables globales mutables, se utilizan tipos de envoltura especiales: Mutex, RwLock, tipos Atomic* o crates externos (lazy_static, once_cell). La inicialización es "perezosa", si se requiere la creación diferida del objeto en el primer acceso.

Ejemplos:

static COUNTER: AtomicUsize = AtomicUsize::new(0); static ref CONFIG: Config = read_config(); // utilizando lazy_static o once_cell

Pregunta engañosa

¿Se puede declarar una variable global mutable sin tipos especiales, si solo se usará desde un solo hilo? ¿Es necesario escribir unsafe?

Respuesta: El compilador requerirá el uso de unsafe en cualquier modificación de una variable global, incluso si la lógica es de un solo hilo. Este es un requisito general para todos los static mut. Solo si la variable está envuelta en una estructura de sincronización (Mutex, atómico, etc.), el compilador permitirá el acceso seguro.

static mut VALUE: i32 = 0; unsafe { VALUE += 1; }

Ejemplos de errores reales debido a la falta de conocimiento sobre los matices del tema


Historia

En un servicio web, al inicializar una caché global se utilizó una variable static normal con una cadena. Varios hilos escribían en ella simultáneamente, causando "bytes" de memoria y caídas de la aplicación debido a la carrera de hilos.


Historia

En una utilidad de línea de comandos en Rust, se modificó una variable estática sin sincronización, porque "solo funciona a través de main". Más tarde, el código se adaptó para la multihilo, olvidando el estado mutable global, lo que causó errores muy difíciles de detectar.


Historia

En un programa embebido, se inicializó incorrectamente el CONFIG static a través de una función al inicio, pero no se garantizó que se llamara exactamente una vez. Como resultado, algunas partes del código accedieron a una configuración no inicializada (referencia nula).