Por que não usar código seguro não gerenciado em C #

10

Existe uma opção no C # para executar o código desmarcado. Geralmente, não é aconselhável fazer isso, pois o código gerenciado é muito mais seguro e supera muitos problemas.

No entanto, pergunto-me, se você tem certeza de que seu código não causará erros e sabe como lidar com a memória, por que (se você gosta de código rápido) segue as orientações gerais?

Estou pensando isso desde que escrevi um programa para uma câmera de vídeo, que exigiu alguma manipulação extremamente rápida de bitmap. Eu mesmo fiz alguns algoritmos gráficos rápidos, e eles funcionam excelente nos bitmaps usando código não gerenciado.

Agora, em geral, imagino que, se você tem certeza de que não possui vazamentos de memória ou riscos de falhas, por que não usar código não gerenciado com mais frequência?

PS: meu histórico: meio que entrei nesse mundo da programação e trabalho sozinho (faço isso por alguns anos) e espero que essa questão de design de software não seja tão estranha. Eu realmente não tenho outras pessoas por aí como um professor para perguntar essas coisas.

user613326
fonte
8
unsafesignifica "saber o que você está fazendo e pesar os benefícios contra os riscos". Eu usei unsafealgumas vezes, e sempre foi para algo muito específico relacionado ao desempenho que poderia ser isolado em seu próprio método. Não o uso como uma técnica de programação geral, pois na maioria das vezes o benefício adicional de desempenho não vale a perda de segurança.
Robert Harvey
14
Escrevi bastante código ao longo dos anos que às vezes travava ou tinha vazamento de memória, que eu tinha certeza de que não tinha vazamento ou risco de travamento.
Whatsisname
11
Aqui está um bom unsafeexemplo de caso de uso: stackoverflow.com/q/11660127/102937
Robert Harvey
3
Eu acho que seu código de bitmap ainda tem erros, mas você simplesmente não os detectou. E mesmo que não seja esse o caso, aguarde até que você implemente alguns novos requisitos no código existente.
Doc Brown
11
Porque mesmo quando você tem certeza de que seu código não causará erros, ele ainda causa erros.
user253751

Respostas:

27

Bem, é principalmente um caso do velho ditado

  • Não otimize
  • (somente para especialistas) Ainda não otimize

Mas, na verdade, posso pensar em três razões principais para evitar código inseguro.

  1. Erros : a parte crítica da sua pergunta é "se você tem certeza de que seu código não causará erros". Bem, como você pode ter certeza absoluta? Você usou um comprovador com método formal que garantiu seu código correto? Uma coisa é certa na programação, e isso é que você terá bugs. Quando você tira uma segurança, permite que novos tipos de bugs se espalhem pela calha. Quando você deixa o coletor de lixo cuidar da memória, muitos problemas desaparecem.

  2. Nem sempre tão rápido quanto você pensa : o outro ponto é: dependendo do problema, o ganho pode não ser tão grande. Embora eu não consiga encontrá-los agora, lembro-me de um estudo do Google comparando a velocidade do Java, Scala, Go e C ++. Uma vez otimizado, é claro que o C ++ era muito mais rápido. Mas o algoritmo programado da maneira "idiomática" não foi realmente muito mais rápido. Idiomatic no sentido de que eles estavam usando estrutura padrão e expressões idiomáticas (container stl, sem loop desenrolado, etc). A Microsoft fez um experimento semelhante com C # e C ++. Raymond Chen, um dos principais engenheiros da Microsoft, teve que escrever sua própria implementação do std :: string para vencer o C #. (consulte: http://www.codinghorror.com/blog/2005/05/on-managed-code-performance-again.html) Por muito menos esforço, você obtém um desempenho decente no código gerenciado, portanto, muitas vezes não vale a pena.

  3. Reutilização : o código não seguro pode ser usado apenas em um ambiente de confiança total. Por exemplo, em um servidor ASP.NET, você geralmente não pode usar código não seguro, pois seria muito fácil introduzir uma vulnerabilidade por excesso de buffer. Outro exemplo seria um clique. Ou se seu aplicativo foi acessado a partir de um compartilhamento de rede. Portanto, se você planeja usar seu código em vários cenários de implantação, o código não seguro está fora do jogo.

Então, basicamente: isso é desaprovado porque pode introduzir bugs desnecessários, pode não ter nenhum ganho e reduzir a reutilização do seu código.

Mas se o seu cenário realmente exige desempenho (e você tem dados para provar isso), você é um programador experiente que sabe como lidar com a memória e seu código será usado em um ambiente controlado; então, com certeza, vá em frente.

Laurent Bourgault-Roy
fonte
4

De certa forma, o código não gerenciado é uma forma de pagamento: você compra uma execução mais rápida com o esforço extra de desenvolvimento. De fato, o código não gerenciado requer mais tempo para desenvolver, depurar e manter. Acertar exatamente é um desafio para a maioria dos participantes. De certa forma, isso é semelhante à programação em assembly: com certeza, você pode extrair mais energia da CPU se escrever no assembly * , mas você "gasta" muito mais esforço nessa rota.

Às vezes, a diferença no tempo de desenvolvimento é muito significativa - dias em vez de horas. No entanto, a diferença na velocidade de execução não é tão dramática. É por isso que o desenvolvimento de código não gerenciado é reservado para situações semelhantes à que você descreveu em suas implementações pós-localizadas e independentes de algoritmos que exigem muitos recursos, como processamento de áudio e vídeo.

Essencialmente, a resposta para sua pergunta é semelhante à resposta de por que todo mundo não dirige a Ferrari: é um carro muito melhor, certo? Felizmente, nem todos podem pagar.


* Os avanços das últimas décadas na tecnologia de otimização em compiladores diminuíram tanto essa lacuna que, no entanto, não é mais uma aposta certa.

dasblinkenlight
fonte
0

Porque ter "certeza" sobre a correção ou qualquer outra restrição no sentido matemático (ou seja, você tem provas) é um problema muito difícil para linguagens imperativas. Os programas geralmente têm um número tão alto de estados que não é possível verificá-los mesmo com a verificação de cada estado possível. E criar uma prova construtiva não é algo que você possa automatizar.

Portanto, o motivo é que os seguros que gerenciam a execução geralmente superam o pequeno ganho de desempenho que você obteria com código não seguro. Obviamente, isso também depende do caso de uso específico.

Tamás Szelei
fonte
11
Eu não acho que tenha algo a ver com a correção ou a simplicidade à razão ..
Jimmy Hoffa
Ninguém está falando de uma prova formal de correção.
11
Tenho certeza de que sua postagem não entendeu o assunto, mas não formulo uma prova formal. Da mesma forma, posso ter certeza de que meu programa está correto (por exemplo, após testes extensivos, depuração e uso prolongado do mundo real sem que ocorram erros) sem provar isso de uma vez por todas. Essa interpretação está muito mais próxima do que a maioria das pessoas quer dizer quando diz "certo que está correto". Os métodos formais são uma preocupação muito específica e completamente desprezada pela maioria dos desenvolvedores.
11
Não vejo essa pergunta. A pergunta, como eu a li, é sobre por que a saída de escape do mundo gerenciado não é / não deve ser usada com mais frequência (o que implica que o código gerenciado por padrão faz sentido). De qualquer forma, se você deseja responder a essa pergunta (apontando a dureza de garantir a correção), você pode fazê-lo sem falar em garantia absoluta e formal de correção. Sua resposta a partir de agora gira exclusivamente em torno de provas completas e corretas de correção para idiomas imperativos. Mas isso é um exagero, e acho que as provas sobre C # gerenciado são igualmente (ou quase tão) difíceis.
11
@ fish: Eu posso ver o que você está dizendo. Existe uma correlação entre algo difícil de provar e algo difícil de raciocinar. Se é difícil provar que está correto, é muito provável que tenha certeza de que está certo.
Michael Shaw
0

Em resumo, nada impede que você faça todo esse trabalho e gerencie as partes do seu programa no ambiente C ++. Como você tem certeza de que pode gerenciar corretamente todos os erros e vazamentos de memória sem o coletor de lixo, faça isso em C ++ :)

Por outro lado, o C # tem vantagens em fornecer um ambiente de desenvolvimento seguro / gerenciado e de tipo forte para executar com segurança no .NET framework.

O possível retrocesso da programação de código não gerenciado é o tempo de desenvolvimento mais longo, a alocação de tempo para testes detalhados. Obviamente, você obterá velocidade de processamento e mais controle sobre como o seu software está sendo executado.

Portanto, a opção para trabalhar com código não gerenciado no .NET Framework a partir do 4.0 é uma opção para casos extremos quando você tem certeza de que isso pode trazer ganhos por não usá-lo ...

Yusubov
fonte
Aha isso é interessante que você vê que eu sou do mundo micro controlador e não se costuma escrever decente c ++, há pouco espaço para erro e bom bom design de software é a principal coisa a fazer
user613326