Translate

viernes, 2 de mayo de 2025

unsafe acceso directo a la memoria en C#


C# es un lenguaje seguro por defecto, lo que significa que evita errores comunes como accesos ilegales a memoria. Sin embargo, hay ocasiones en las que necesitamos un control más bajo nivel, como en interoperabilidad con código nativo o para optimizaciones de rendimiento. Para eso existe la palabra clave unsafe

La palabra clave unsafe en C# habilita el uso de punteros, acceso directo a memoria y operaciones que normalmente están fuera del alcance del entorno de ejecución administrado del .NET runtime. En otras palabras, permite usar características similares a C/C++, con sus pros y contras.

Para usarlo, debés marcar bloques, métodos o estructuras con la palabra clave unsafe. También tenés que habilitarlo en el proyecto.

En el `.csproj`:


<PropertyGroup>

  <AllowUnsafeBlocks>true</AllowUnsafeBlocks>

</PropertyGroup>


Veamos un ejemplo: 


unsafe

{

    int valor = 42;

    int* puntero = &valor;


    Console.WriteLine(*puntero); // Imprime 42

}


Cuando queremos apuntar a arrays o strings, que son gestionados por el Garbage Collector, necesitamos usar fixed para evitar que el objeto se mueva en memoria:


unsafe

{

    int[] numeros = { 10, 20, 30 };

    fixed (int* p = numeros)

    {

        Console.WriteLine(p[1]); // Imprime 20

    }

}



Que podemos hacer con unsafe?

  • Declaración y uso de punteros (`*`, `&`)
  • Indexación de punteros (`p[i]`)
  • Aritmética de punteros (`p++`, `p + 1`, etc.)
  • Conversión entre tipos de punteros
  • Uso de `sizeof(T)` para tipos primitivos


Pero ¿Cuándo usamos unsafe?

  • Interop con librerías nativas (C, C++, DLLs).
  • Manipulación avanzada de memoria.
  • Procesamiento de imágenes o buffers donde la performance es crítica.
  • Serialización binaria de alto rendimiento.

Como se pueden imaginar esto es tan util como peligroso, que es lo que puede salir mal?

  • Podemos introducir errores difíciles de depurar (como corrupción de memoria).
  • Desactiva algunas protecciones del CLR.
  • El código unsafe no se ejecuta en entornos con restricciones de seguridad (como ciertos sandboxes).
  • No es portable entre arquitecturas de forma garantizada.


Dentro de unsafe, podemos usar sizeof` para obtener el tamaño de tipos primitivos:


unsafe

{

    Console.WriteLine(sizeof(int));   // 4

    Console.WriteLine(sizeof(byte));  // 1

}


También podés usarlo con nint, nuint, float, double, etc.

Si queremos evitar unsafe pero aún así trabajar con memoria de forma eficiente:



El modo unsafe en C# te da acceso a un poder inmenso, pero con gran responsabilidad. Es una herramienta útil para situaciones específicas donde el rendimiento o la interoperabilidad lo justifican, pero debe usarse con precaución y conocimiento.