name keywords google etiquetas ejemplos description c# .net unsafe

c# - keywords - ¿Por qué este código funciona sin la palabra clave insegura?



meta tags google (3)

OK, eso es desagradable ... los peligros de usar una unión. Eso puede funcionar, pero no es una buena idea, creo que lo compararía con la reflexión (donde puedes hacer la mayoría de las cosas). Me interesaría ver si esto funciona en un entorno de acceso restringido; si es así, puede representar un problema mayor ...

Acabo de probarlo sin el indicador "Full Trust", y el tiempo de ejecución lo rechaza:

No se pudo cargar el tipo ''MemoryAccess'' desde el ensamblado ''ConsoleApplication4, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null'' porque los objetos se superponen en el offset 0 y el ensamblaje debe ser verificable.

Y para tener esta bandera, ya necesitas mucha confianza, por lo que ya puedes hacer más cosas desagradables. Las cadenas son un caso ligeramente diferente, porque no son objetos normales de .NET, pero hay otros ejemplos de formas de mutarlos, aunque el enfoque de "unión" es interesante. De otra manera hacky (con suficiente confianza):

string orig = "abc ", copy = orig; typeof(string).GetMethod("AppendInPlace", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(int) }, null) .Invoke(orig, new object[] { "def", 3 }); Console.WriteLine(copy); // note we didn''t touch "copy", so we have // mutated the same reference

En respuesta a su propia pregunta controvertida , Mash ha ilustrado que no necesita la palabra clave "insegura" para leer y escribir directamente en los bytes de cualquier instancia de objeto .NET. Puede declarar los siguientes tipos:

[StructLayout(LayoutKind.Explicit)] struct MemoryAccess { [FieldOffset(0)] public object Object; [FieldOffset(0)] public TopBytes Bytes; } class TopBytes { public byte b0; public byte b1; public byte b2; public byte b3; public byte b4; public byte b5; public byte b6; public byte b7; public byte b8; public byte b9; public byte b10; public byte b11; public byte b12; public byte b13; public byte b14; public byte b15; }

Y luego puedes hacer cosas como cambiar una cadena "inmutable". El siguiente código imprime "barra" en mi máquina:

string foo = "foo"; MemoryAccess mem = new MemoryAccess(); mem.Object = foo; mem.Bytes.b8 = (byte)''b''; mem.Bytes.b10 = (byte)''a''; mem.Bytes.b12 = (byte)''r''; Console.WriteLine(foo);

También puede activar una AccessViolationException corrompiendo las referencias de objetos con la misma técnica.

Pregunta: Pensé que (en código C # administrado puro) la palabra clave unsafe era necesaria para hacer cosas como esta. ¿Por qué no es necesario aquí? ¿Significa esto que el código puro "seguro" administrado no es realmente seguro en absoluto?


Todavía está optando por salir del bit ''gestionado''. Existe la suposición subyacente de que si puedes hacer eso, entonces sabes lo que estás haciendo.


Vaya, me he peleado unsafe con fixed . Aquí hay una versión corregida:

La razón por la que el código de ejemplo no requiere etiquetado con la palabra clave unsafe es que no contiene punteros (consulte la siguiente cita para ver por qué esto se considera inseguro). Usted tiene toda la razón: "seguro" podría denominarse "amigable con el tiempo de ejecución". Para obtener más información sobre este tema, le remito a Don Box y Chris Sells Essential .NET

Para citar MSDN,

En el Common Language Runtime (CLR), el código no seguro se conoce como código no verificable. El código inseguro en C # no es necesariamente peligroso; es solo un código cuya seguridad no puede ser verificada por el CLR. Por lo tanto, el CLR solo ejecutará código no seguro si se encuentra en un ensamblaje totalmente confiable. Si usa un código inseguro, es su responsabilidad asegurarse de que su código no introduzca riesgos de seguridad o errores de puntero.

La diferencia entre fijo e inseguro es que fijo evita que el CLR mueva las cosas en la memoria, de modo que las cosas fuera del tiempo de ejecución puedan acceder a ellas de manera segura, mientras que inseguro es exactamente el problema opuesto: mientras que el CLR puede garantizar la resolución correcta para un Referencia de punto de red, no puede hacerlo para un puntero. Puede recordar que varios Microsofties están hablando sobre cómo una referencia no es un indicador, y es por eso que hacen tanto alboroto sobre una distinción sutil.