En esta guía, exploraremos el código inseguro. Cuando hablamos de código inseguro en C#, estamos hablando de cuando ejecutamos código sin la supervisión del CLR – abreviatura de Common Language Runtime. Hay punteros en C# que puedes usar para determinar si el código es inseguro.= No es una ciencia exacta pero estamos aquí para arrojar algo de luz sobre este misterio.
¿Qué es CLR?
El Common Language Runtime controla la ejecución de los programas .NET, desde la carga a la memoria hasta el manejo de excepciones y la seguridad de los tipos. Hay numerosas facilidades proporcionadas por el CLR. Hay dos facilidades principales proporcionadas por el CLR. La primera es el Recolector de Basura y la segunda es la Administración de Hilos. La recolección de basura se explica en detalle en mi guía sobre los Destructores.

Hay dos componentes principales del marco .NET:
- BCL (Base Class Library)
- CLR (Common Language Runtime)
El BCL no es más que la biblioteca estándar .NET, a la que se puede acceder a través de aplicaciones de consola, aplicaciones WPF, aplicaciones ASP.NET, etc. Es un conjunto de clases y funcionalidades predefinidas que puedes reutilizar. Esto te permite construir tu aplicación más rápido y hacerla portátil en diferentes máquinas que comparten una versión .NET compatible. También reduce el tamaño de tus aplicaciones.
El BCL puede ser dividido en dos partes más:
- CTS (Especificación Común de Tipos)
- CLS (Especificación de lenguaje común)
Necesitamos aclarar dos conceptos más que son necesarios para entender lo que significa el código inseguro, y su ejecución.
Dos tipos de código.
- Código administrado (código seguro)
- Código no gestionado (también conocido como código inseguro)
El código administrado funciona completamente bajo la supervisión del CLR. Se rastrea y se recoge la basura automáticamente; también tiene acceso a todo el arsenal de instalaciones proporcionadas por el CLR. El código no administrado no puede ser ejecutado por el CLR. Se utiliza en conjunto con las instalaciones proporcionadas por el Sistema Operativo. Los recursos, como archivos, flujos de red, flujos de medios y aplicaciones, que interactúan con estos recursos suelen ser código no administrado y se consideran menos seguros. Cuando estamos trabajando, por ejemplo, en una aplicación que es capaz de editar un archivo de vídeo, nuestra aplicación normalmente necesita encargarse de abrir, editar y cerrar los recursos. De lo contrario, puede corromperse y el reproductor de medios puede negarse a manejarlo.
Introducir punteros
Los punteros sólo se interpretan en el contexto de un código inseguro o no gestionado. El puntero puede ser un tipo de puntero, un tipo de valor o un tipo de referencia.
Para definir un puntero, necesitamos el siguiente código.
12int* myIntPointer;void* myVoidPointer;
csharp
El nombre del tipo definido antes del * se llama referente . Los tipos punteros no heredan de la clase base del objeto , y no hay conversión entre los tipos punteros y la clase base del objeto . Boxing y Unboxing tampoco soportan punteros.
También puedes definir múltiples punteros en la misma línea.
1int* mageDamage, barbarianDamage, amazonDamage, rogueDamage;
csharp
El recolector de basura no protege las referencias de los objetos, lo que significa que, aunque un puntero señale una referencia o una estructura que contenga referencias, el recolector de basura puede recogerla. Por lo tanto, está prohibido que un puntero señale:
- Una referencia.
- Una estructura que contiene referencias.
Puedes definir diferentes tipos de punteros:
- int* p – puntero a un número entero.
- int** p – puntero a un puntero a un entero.
- int*[] p – un conjunto de punteros a números enteros.
- char* p – puntero a un personaje.
- void* p – puntero a un tipo desconocido.
Atravesemos una serie de números impares con la ayuda de punteros.
123456789101112131415161718int[] a =newint[5]{3,5,7,9,11};unsafe{fixed(int* p =&a[0]){int* p2 = p; Console.WriteLine(*p2); p2 +=1; Console. WriteLine(*p2); p2 +=1; Console.WriteLine(*p2); p2 +=1; Console.WriteLine(*p2); p2 +=1; Console.WriteLine(*p2);//Dereferencing*p +=1; Console.WriteLine(*p);}}
csharp
La salida del código una vez ejecutado debería verse así.
1234563579114
bash
La palabra clave insegura marca la sección del código para el compilador que señalará. La palabra clave fija significa que fijamos la variable *p en la parte superior de nuestro montón. La última línea *p += 1 se llama derivación. Dereferenciación significa que sobreescribimos el valor referenciado por el puntero, y luego tomamos el valor actual y lo incrementamos en uno. Esto sólo funciona porque nuestra matriz contiene números enteros, que son compatibles con el operador; otros tipos arrojarían un error. Para ejecutar este código, hay que pasar el interruptor -unsafe o el /unsafe , dependiendo del compilador. Si usas Visual Studio, necesitas permitir la ejecución y compilación de código inseguro porque, por defecto, está deshabilitado y te lanzará un bonito error advirtiéndote sobre la seguridad.
Hay una lista de operadores y declaraciones que puede utilizar para manipular sus indicaciones en un contexto inseguro.
Operadores:
- —- miembro accesorio para struct
- [] — indexación
- & — dirección de una variable
- –, ++ — incremento y decremento
- -, + — Aritmético
- ==, !=, <,, <=, — Comparar
Declaraciones:
- stackalloc – Asignando memoria en la pila.
- fijo – Variable fija temporal para encontrar su dirección.
Propiedades del código inseguro:
- Los métodos, tipos y bloques de código pueden definirse como inseguros
- Se requiere un código inseguro para las funciones nativas que dependen de punteros
- El código inseguro introduce riesgos para la seguridad y la estabilidad
- Los códigos que contienen bloques inseguros deben ser compilados con -inseguro
- En algunos casos, el código inseguro puede dar lugar a un mejor rendimiento porque se eliminan las comprobaciones de la matriz.
Contenidos