tag - Código con comportamiento indefinido en C#
summary example c# (7)
En C ++ hay muchas maneras de escribir código que compila, pero produce un comportamiento indefinido (Wikipedia) . ¿Hay algo similar en C #? ¿Podemos escribir código en C # que compila, pero tiene un comportamiento indefinido?
¡Sí! ¡Existe, incluso en un contexto seguro! (Bueno, su implementación se define como indefinida, al menos)
Aquí hay uno de Marek Safar y VSadov en los números de Roslyn . Hay una falta de coincidencia entre C # y el CLI con respecto a bool
.
C # cree que solo hay un tipo de true
y un tipo de false
.
CLI cree que false
es un byte que contiene 0, y todos los demás valores son true
.
Esta discrepancia significa que podemos obligar a C # a hacer algo de cosas (marginalmente) interesantes:
//non-standard bool
//We''re setting a bool''s value to a byte value of 5.
var a = new bool[1];
Buffer.SetByte(a, 0, 5);
//non-standard bool
//We''re setting a bool''s value to a byte value of 10.
var b = new bool[1];
Buffer.SetByte(b, 0, 10);
//Both are true.
Console.WriteLine(a[0]);
Console.WriteLine(b[0]);
//But they are not the same true.
Console.WriteLine(a[0] == b[0]);
Los resultados anteriores:
true
true
false
Curiosamente, el depurador no está de acuerdo (debe evaluar la verdad de manera diferente?)
De todos modos, la conclusión a la que parece haber llegado el equipo de C # es (énfasis añadido):
IE, el lenguaje permanecerá completamente despreocupado sobre los bools no estándar. La implementación particular (como en MS C # en CIL) reconocerá la existencia de bools no estándar y especificará su comportamiento como indefinido.
Al mirar el Wiki, las situaciones en las que ocurre un comportamiento indefinido no están permitidas o arrojan una excepción en C #.
Sin embargo, en un código inseguro, creo que es posible un comportamiento indefinido, ya que eso le permite usar punteros, etc.
Editar: Parece que tengo razón: http://msdn.microsoft.com/en-us/library/aa664771%28VS.71%29.aspx
Tiene un ejemplo de comportamiento indefinido en c #
Como otros han mencionado, casi cualquier cosa en el bloque "inseguro" puede generar un comportamiento definido por la implementación; El uso indebido de bloques inseguros le permite cambiar los bytes de código que componen el tiempo de ejecución, y por lo tanto todas las apuestas están desactivadas.
El caso de la esquina de la división entera tiene un comportamiento definido por la implementación.
Lanzar una excepción y no detectarla causa un comportamiento definido por la implementación: finaliza el proceso, inicia un depurador, etc.
Hay otras situaciones en C # en las que nos vemos obligados a emitir código que tiene un comportamiento determinado por la implementación. Por ejemplo, esta situación:
http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
Sin embargo, las situaciones en las que un programa seguro y de buen comportamiento C # tiene un comportamiento definido por la implementación deberían ser bastante raras.
De acuerdo con el documento ECMA-334 (página 473):
Un programa que no contiene ninguna ocurrencia del modificador inseguro no puede mostrar ningún comportamiento indefinido.
Eso promueve la "implementación definida" para el peor de los casos, ver la respuesta de Eric Lippert.
En general, diría que no.
Use la variable automática antes de inicializarla.
Todas las variables deben ser inicializadas. Si no se produce una excepción.
División por cero
Se lanza una excepción.
Indexar una matriz fuera de los límites
Se lanza una excepción
Como señaló Aequitarum Custos, puedes usar un código inseguro. Por otra parte, esto no es realmente C #, estás expirando explícitamente del entorno C #.
Muchos y subprogramas tienen requisitos que pueden resumirse como:
Cuando se le den datos válidos, produzca resultados válidos.
Abstenerse de lanzar misiles nucleares o negar las leyes del tiempo y la causalidad, incluso cuando se les den datos inválidos.
Uno de los principales objetivos de diseño de los lenguajes Java y .NET es que, a menos que el código utilice ciertos que están marcados como "inseguros", generalmente no se requieren esfuerzos especiales para cumplir con la segunda restricción anterior [aunque algunos comportamientos relacionados con la recolección de basura y Finalize
puede ser un poco extraño desde el punto de vista tiempo / causalidad, esos pueden describirse como excepciones a las reglas normales de causalidad, en lugar de una revocación total de ellas]. Esa situación es muy diferente de la situación en C, donde muchos tipos de errores dependientes de datos (p. Ej., Desbordamiento de enteros) pueden dar como resultado que los compiladores se comporten de forma arbitraria, lo que incluye hacer las suposiciones necesarias para evitar el desbordamiento. Los tipos realmente horribles de Comportamiento Indefinido que se fomentan en la filosofía C hipermoderna no existen en C # u otros lenguajes .NET fuera de los bloques "inseguros".
No exactamente en el sentido exactamente Wiki pero supongo que el ejemplo más obvio que se me viene a la mente es simplemente escribir algún código enhebrado, pero luego es así en cualquier idioma.