¿Qué hace patrones-de-seguridad-de-memoria?
Implementa programación segura en memoria con RAII, propiedad, punteros inteligentes y gestión de recursos en Rust, C++ y C. Útil al escribir código de sistemas seguro, gestionar recursos o prevenir errores de memoria.
Introducción
Este skill proporciona patrones y guías para prevenir errores de memoria comunes como fugas de memoria, dobles liberaciones, uso después de liberación (use-after-free) y desbordamientos de búfer. Se centra en tres lenguajes principales: Rust, C++ y C, cada uno con sus propias estrategias de seguridad.
Lenguajes y Patrones
Rust
- Propiedad (Ownership): Cada valor tiene un único dueño. Al transferir la propiedad, el dueño anterior no puede usar el valor.
- Préstamo (Borrowing): Permite acceder a un valor sin transferir la propiedad, mediante referencias inmutables (
&T) o mutables (&mut T). - Duración (Lifetimes): El compilador verifica que las referencias no sobrevivan a los datos a los que apuntan.
- Punteros inteligentes:
Box<T>,Rc<T>,Arc<T>,RefCell<T>para gestión de memoria en montículo y conteo de referencias.
C++
- RAII (Resource Acquisition Is Initialization): Asociar la adquisición de recursos con la inicialización de objetos y su liberación con la destrucción.
- Punteros inteligentes:
std::unique_ptr,std::shared_ptr,std::weak_ptrpara gestión automática de memoria. - Movimiento (Move semantics): Transferencia eficiente de recursos con
std::move. - Contenedores estándar:
std::vector,std::string, etc., que gestionan su propia memoria.
C
- Asignación y liberación manual:
malloc,calloc,realloc,free. - Patrones de gestión: Establecer punteros a
NULLdespués de liberar, comprobar valores devueltos por funciones de asignación. - Análisis estático: Uso de herramientas como Valgrind, AddressSanitizer para detectar fugas y corrupción.
Mejores Prácticas
- Preferir RAII: En C++ y Rust, usar RAII para recursos (memoria, archivos, sockets).
- Evitar punteros crudos en C++: Usar
std::unique_ptrostd::shared_ptren lugar denew/delete. - Usar contenedores estándar: En C++,
std::vectorystd::stringgestionan memoria automáticamente. - En Rust, confiar en el compilador: Los errores de préstamo se detectan en tiempo de compilación.
- En C, inicializar siempre los punteros: Asignar
NULLdespués defreepara evitar usos colgantes.
Ejemplo Rápido
Rust
fn main() {
let data = Box::new(42); // Propiedad transferida a data
println!("{}", data); // data se libera al salir del ámbito
}
C++
#include <memory>
int main() {
auto ptr = std::make_unique<int>(42); // Puntero inteligente
// No es necesario delete
return 0;
}
C
#include <stdlib.h>
int main() {
int *ptr = (int*)malloc(sizeof(int));
if (ptr) {
*ptr = 42;
free(ptr);
ptr = NULL; // Evitar uso colgante
}
return 0;
}
Advertencias
- No mezclar estilos: En C++, no mezclar
new/deletecon punteros inteligentes a menos que sea necesario. - Ciclos de referencia en Rust: Con
Rc/RefCell, pueden ocurrir fugas de memoria si hay ciclos; usarWeakpara romperlos. - Aliasing en C: El uso de punteros a la misma memoria puede causar comportamientos indefinidos; usar
restrictcuando sea posible.
Compatibilidad
- Rust: 1.0+
- C++: C++11+
- C: C99+