Código com comportamento indefinido em C#
-
13-09-2019 - |
Pergunta
Em C++ existem um monte de maneiras que você pode escrever um código que compila, mas produz comportamento indefinido (Wikipédia).Existe algo semelhante em C#?Podemos escrever código em C# que compila, mas tem um comportamento indefinido?
Solução
Como outros mencionaram, praticamente qualquer coisa no bloco "inseguro" pode produzir comportamentos definidos pela implementação; O abuso de blocos inseguros permite alterar os bytes de código que compõem o próprio tempo de execução e, portanto, todas as apostas estão desativadas.
O caso de canto de divisão inteira tem um comportamento definido por implementação.
Jogar uma exceção e nunca capturar isso causa comportamento definido pela implementação-encerrar o processo, iniciar um depurador e assim por diante.
Existem várias outras situações em C#, onde somos forçados a emitir código que tem comportamento determinado por implementação. Por exemplo, esta situação:
http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
No entanto, as situações em que um programa C# seguro e bem-comportado tem comportamento definido por implementação deve ser bastante raro.
Outras dicas
Sim! Há, mesmo em um contexto seguro! (Bem, é implementação definida para ser indefinida, pelo menos)
Aqui está um de Marek Safar e Vsadov no Problemas de Roslyn. Há uma incompatibilidade entre C# e a CLI em relação a bool
.
C# acredita que existe apenas um tipo de true
, e um tipo de false
.
A CLI acredita nisso false
é um byte contendo 0, e todos os outros valores são true
.
Esta discrepância significa que podemos coagir C# para fazer algum A (marginalmente) interessante coisas coisa:
//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]);
As saídas acima:
true
true
false
Curiosamente, o depurador discorda (deve avaliar a verdade de maneira diferente?)
De qualquer forma, a conclusão que a equipe C# parece ter chegado (ênfase adicionada):
Ou seja, o idioma permanecerá totalmente despreocupado com as bools fora do padrão. A implementação específica (como no MS C# no CIL) reconhecerá a existência de bools fora do padrão e especificará seu comportamento como Indefinido
Olhando para o wiki, as situações em que o comportamento indefinido acontece não são permitidos ou lançam uma exceção em C#.
No entanto, em código inseguro, o comportamento indefinido, acredito ser possível, pois isso permite que você use ponteiros etc.
EDIT: Parece que estou certo: http://msdn.microsoft.com/en-us/library/aa664771%28vs.71%29.aspx
Tem um exemplo de comportamento indefinido em C#
De acordo com o documento ECMA-334 (p. 473):
Um programa que não contém nenhuma ocorrência do modificador inseguro não pode exibir nenhum comportamento indefinido.
Isso promove a 'implementação definida' para o pior caso, consulte a resposta de Eric Lippert.
Muitos e subprogramas têm requisitos que podem ser resumidos como:
Quando receber dados válidos, produza saída válida.
Evite o lançamento de mísseis nucleares ou negar as leis do tempo e da causalidade, mesmo quando recebem informações inválidas.
Um dos principais objetivos de design das línguas Java e .NET é que, a menos que o código use certo que seja marcado como "inseguro", nenhum esforço específico geralmente é necessário para atender à segunda restrição acima [embora alguns comportamentos relacionados à coleta de lixo e Finalize
pode ser um pouco estranho desde o ponto de vista do tempo/causalidade, aqueles podem ser descritos como exceções às regras normais de causalidade, em vez de uma revogação total deles]. Essa situação é muito diferente da situação em C, onde muitos tipos de erros dependentes de dados (por exemplo, transbordamento inteiro) podem resultar em compiladores se comportando de maneira arbitrária, incluindo fazer as suposições necessárias para evitar transbordar. Os tipos verdadeiramente horríveis de comportamento indefinido que são incentivados na filosofia h hipermoderna não existem em C# ou em outras línguas .NET fora dos blocos "inseguros".
Não no sentido exatamente do Wiki, mas suponho que o exemplo mais óbvio que me venha é simplesmente escrever algum código roscado, mas é assim em qualquer idioma.
Em geral, eu diria que não.
Utilize a variável antes de ser inicializado.
Todas as variáveis devem ser inicializado.Se não ocorre uma exceção.
Divisão por zero
Exceção é lançada.
A indexação de uma matriz fora dos limites
Exceção é lançada
Como Aequitarum Custos apontado você pode usar o código não seguro.Então, novamente, este não é realmente C#, você está explicitamente optar fora do C# ambiente.