Em Quando usar C sobre C ++ e C ++ sobre C? há uma declaração errada. para codificar exceções de tamanho / C ++:
Jerry responde (entre outros pontos):
(...) tende a ser mais difícil produzir executáveis verdadeiramente minúsculos com C ++. Em sistemas realmente pequenos, você raramente escreve muito código, e o (...)
ao qual perguntei por que isso seria, ao qual Jerry respondeu:
o principal é que o C ++ inclui manipulação de exceção, que (pelo menos geralmente) adiciona um mínimo ao tamanho do executável. A maioria dos compiladores permitirá que você desabilite o tratamento de exceções, mas quando você faz o resultado, não é mais C ++. (...)
o que realmente não duvido no nível técnico do mundo real.
Portanto, estou interessado (por curiosidade) em ouvir exemplos do mundo real em que um projeto escolheu C ++ como idioma e, em seguida, optou por desativar as exceções. (Não apenas "não use" exceções no código do usuário, mas desative-as no compilador, para que você não possa lançar ou capturar exceções.) Por que um projeto optou por fazê-lo (ainda usando C ++ e não C, mas não exceções) - quais são / foram as razões (técnicas)?
Adendo: Para aqueles que desejam elaborar suas respostas, seria bom detalhar como são tratadas as implicações das não-exceções:
- Coleções STL (
vector
, ...) não funcionam corretamente (falha na alocação não pode ser relatada) new
não pode jogar- Construtores não podem falhar
fonte
Respostas:
Quase todos os jogos de console disponíveis em C ++, com a exceção desativada, ainda hoje. Em vista disso, é a configuração padrão para compiladores C ++ direcionados para esses consoles. Às vezes, não é garantido que alguns recursos do C ++ funcionem corretamente nesses compiladores, como herança múltipla (por exemplo, estou pensando em um compilador padrão do console muito conhecido).
Além disso, outro exemplo é o SDK do hardware do Arduino, usando o gcc sem exceção, ativado no C ++, e outras coisas como nenhum STL fornecido .
Existem algumas razões técnicas, boas ou ruins, qualquer que seja, não é meu conselho, mas razões que ouvi:
Acho que as exceções podem ser úteis, mesmo em jogos, mas é verdade que em jogos de console não é realmente útil.
Atualizar:
Estou adicionando outro exemplo surpreendente aqui: o LLVM / CLang não usa exceção nem RTTI pelos seguintes motivos :
O CLang é conhecido por sua velocidade de compilação e erros explícitos, mas também é um compilador raro que possui um código realmente fácil de seguir.
fonte
Jerry disse: ... o resultado não é mais C ++ , enquanto minha metáfora é que é claramente C ++, apenas um dialeto ligeiramente diferente porque os programas utilizam outras formas, convenções e estilos de escrita.
Aqui estão meus principais motivos para desativá-los:
Compatibilidade binária
O cruzamento de fronteiras de idioma e tradução não é universalmente bem definido ou indefinido. Se você deseja garantir que seu programa opere no domínio do comportamento definido, será necessário colocar em quarentena as exceções nos pontos de saída do módulo.
Tamanho do executável
Aqui estão os tamanhos binários de um programa livre de exceção que escrevi, construído sem e com as exceções ativadas:
Sem exceções:
Com exceções:
Lembrete: é uma coleção de bibliotecas e programas que contêm zero jogadas / capturas. A bandeira compilador faz permitir exceções na biblioteca padrão do C ++. Portanto, o custo no mundo real é superior a 19% visto neste exemplo.
Compilador: apple gcc4.2 + llvm. Tamanhos em MB.
Rapidez
Apesar do termo "exceções de custo zero", elas ainda adicionam alguma sobrecarga, mesmo quando nada é lançado. No caso acima, é um programa crítico de desempenho (processamento, geração, apresentação, conversões de sinais, com grandes conjuntos de dados / sinais etc.). Exceções não são um recurso necessário neste design, enquanto o desempenho é muito importante.
Correção do programa
Parece um motivo estranho ... Se jogar não é uma opção, você deve escrever programas relativamente rigorosos, corretos e bem testados para garantir que seu programa seja executado corretamente e que os clientes usem as interfaces corretamente (se você me der um argumento ruim ou não) Para verificar um código de erro, você merece UB). O resultado? A qualidade da implementação melhora muito e os problemas são corrigidos rapidamente.
Simplicidade
As implementações de manipulação de exceção nem sempre são atualizadas. Eles também adicionam muita complexidade, porque uma implementação pode ter muitas sequências de saída. É mais simples ler e manter programas altamente complexos quando eles usam um pequeno conjunto de estratégias de saída bem definidas e digitadas, que passam por bolhas e são tratadas pelo cliente. Em outros casos, as implementações podem, com o tempo, implementar mais lances ou suas dependências podem introduzi-las. Os clientes não podem se defender fácil ou adequadamente contra todas essas saídas. Eu escrevo e atualizo muitas bibliotecas, há evolução e aprimoramento freqüentes. Tentar manter isso tudo sincronizado com as seqüências de saída de exceção (em uma grande base de código) não seria um bom uso do tempo e provavelmente adicionaria muito ruído e sujeira. Devido ao aumento da correção do programa e a mais testes,
Histórico / Código Existente
Em alguns casos, eles nunca foram introduzidos por razões históricas. Uma base de código existente não os utilizava, alterar os programas poderia levar anos-homem e tornar a manutenção realmente feia devido à sobreposição de convenções e implementações.
Desvantagens
Obviamente, existem desvantagens, as maiores são: Incompatibilidade (inclusive binária) com outras bibliotecas e o fato de que você precisará implementar uma boa quantidade de programas para se ajustar a esse modelo.
fonte
malloc
devoluções0
), o alocador entra em umwhile (1)
que possui uma alternância de contexto, seguido por outra tentativa de alocação. Nessa base de código, costumava ser novo por meio do alocador retornar 0, mas a implementação mais recente estava funcionando bem. (cont)O Google não aprova exceções no Guia de Estilo C ++ , principalmente por motivos históricos:
(Ênfase do editor)
fonte
O Qt quase nunca usa exceções. Erros no Qt são significados com códigos e sinais de erro. O motivo declarado oficialmente é:
Hoje, uma crítica comum ao Qt é que sua exceção de segurança não está completa.
fonte
O Symbian C ++ (usado em alguns telefones celulares Nokia) não usa exceções, pelo menos não diretamente, porque os compiladores C ++ não os implementaram de maneira confiável quando o Symbian foi desenvolvido.
fonte
Eu / nunca / uso exceções. Há várias razões para isso, mas as duas principais razões são que eu nunca precisei delas para produzir código robusto e que reduzam o desempenho em tempo de execução.
Eu trabalhei no código de produção que está usando e desativando exceções - o código que permitia exceções era uniformemente pior. Em alguns lugares, foram usadas exceções para controle de fluxo genuíno, em vez de tratamento de erros, que é muito pesado, anti-desempenho e difícil de depurar. Em geral, os problemas de depuração no código cheio de exceção eram mais difíceis do que no código livre de exceção - em parte devido à pilha e às dificuldades intrínsecas do mecanismo de exceção, mas muito mais do que isso, devido ao código lento que era incentivado como resultado de ter manipulação de exceção disponível.
Não há nada seriamente errado com as exceções em si / se você não se importa com desempenho / e não tem tempo para fazer algo corretamente - elas são um recurso de linguagem para tratamento de erros e um bom substituto para um mecanismo adequado de tratamento de erros. No entanto, quase sempre existem / melhores / maneiras de lidar com erros - como com sua própria lógica (é difícil elaborar isso - é quase senso comum). Se não for um erro seu, mas for proveniente de uma biblioteca (por exemplo, a biblioteca padrão), você deverá respeitar a escolha de exceções ou sofrer alguma falha, mas eu sempre questionaria essa opção. Nunca vi uma situação em que as exceções fossem realmente a melhor solução.
As asserções são mais debugáveis, os códigos de erro são menos pesados ... entre os dois, se usados corretamente, você fica mais fácil de ler, depurar e manter o código mais rápido. Suas vitórias por toda parte ...
fonte
No padrão de codificação Joint Strike Fighter C ++ de Bjarne et. al., as exceções são proibidas devido aos rígidos requisitos em tempo real dos caças.
Citado nas perguntas frequentes em C ++ de Bjarne .
Lembre-se, o C ++ provavelmente executa a mais ampla variedade de software de todos os idiomas ...
fonte
É meio importante no design da biblioteca C ++. Muitas vezes, com uma interface C, é meio desagradável lançar uma exceção da sua biblioteca de terceiros para o cliente. Aponte que, se sua biblioteca é lançada, você está cortando um conjunto de clientes que a teriam usado, uma vez que ela tinha uma garantia de exclusão (por qualquer razão que o cliente tenha para restringir as exceções).
Pessoalmente, vi exceções abusadas quando a equipe é instruída a "lançar uma exceção" sempre que algo não tão terrível acontece. É claro que você vê o erro aqui - a exceção foi lançada no código antes que alguém descobrisse o que fazer com ele. Esse projeto teve algumas falhas, já que esses arremessos profundos se revezavam ocasionalmente.
fonte
Talvez a esse respeito, vale a pena mencionar o C ++ incorporado . O C ++ incorporado é uma variante do C ++ projetada (obviamente o suficiente) para sistemas embarcados. É basicamente um subconjunto adequado de C ++, com (entre outras coisas) modelos, namespaces e manipulação de exceção removidos.
Devo acrescentar que, embora o EC ++ tenha causado algum estrago quando era novo, eles parecem ter ficado bastante silenciosos. Não sei se as pessoas perderam o interesse ou se a primeira tentativa foi tão perfeita que ninguém viu motivo para mexer com isso por uma década.
<closed captioning for the humor impaired>Yeah, right!</closed captioning>
fonte
Um bom exemplo é a programação no modo kernel.
Você pode usar o C ++ lá para obter um código mais limpo, mas sem exceções. Não há biblioteca de tempo de execução para eles, e o tratamento de exceções usa muita memória de pilha que é muito limitada no kernel (experimentei exceções C ++ no kernel do Windows NT e o lançamento e desenrolamento de exceção consome metade da pilha disponível - muito fácil de obter o estouro da pilha e travar todo o sistema).
Normalmente você define seus próprios operadores
new
edelete
. Também achei bastante úteis as referências aplacement new
e c ++ 11 rvalue. Nenhuma STL ou outras bibliotecas em modo de usuário C ++ que dependem de exceções podem ser usadas.fonte
Quando você está tentando manter a memória executável baixa. Normalmente feito em sistemas embarcados (ou móveis). Para aplicativos de desktop, nunca é necessário, no entanto, em servidores, pode ser considerado se você deseja o máximo de memória ram possível para o servidor web ou para sql.
fonte