Uma pergunta comum, aqui e em outros lugares. O C ++ é adequado para sistemas embarcados?
Microcontroladores? RTOSes? Torradeiras? PCs incorporados?
OOP é útil em microcontroladores?
O C ++ remove o programador muito longe do hardware para ser eficiente?
O C ++ do Arduino (sem gerenciamento dinâmico de memória, modelos, exceções) deve ser considerado como "C ++ real"?
(Espero que este wiki sirva como um local para conter essa guerra santa em potencial)
microcontroller
embedded
programming
c++
Toby Jaffey
fonte
fonte
Respostas:
Sim, o C ++ ainda é útil em sistemas incorporados. Como todo mundo já disse, ainda depende do sistema em si, como um uC de 8 bits provavelmente seria um não-não no meu livro, embora exista um compilador por aí e algumas pessoas o façam (estremecem). Ainda há uma vantagem em usar C ++, mesmo quando você o reduz para algo como "C +", mesmo em um micro mundo de 8 bits. O que quero dizer com "C +"? Quero dizer, não use new / delete, evite exceções, evite classes virtuais com herança, possivelmente evite a herança todos juntos, tenha muito cuidado com os modelos, use funções embutidas em vez de macros e use
const
variáveis em vez de#defines
.Trabalho com C e C ++ em sistemas embarcados há mais de uma década, e parte do meu entusiasmo juvenil por C ++ definitivamente desapareceu devido a alguns problemas do mundo real que abalam a ingenuidade. Vi o pior do C ++ em sistemas embarcados aos quais gostaria de me referir como "programadores de CS enlouquecidos em um mundo de EE". Na verdade, é nisso que estou trabalhando com meu cliente para melhorar essa base de código que eles têm, entre outros.
O perigo do C ++ é porque é uma ferramenta muito poderosa, semelhante a uma espada de dois gumes que pode cortar tanto seu braço quanto sua perna se não for educada e disciplinada adequadamente em sua linguagem e programação geral. C é mais como uma faca de um gume, mas ainda é tão afiada. Com o C ++, é muito fácil obter altos níveis de abstração e criar interfaces ofuscadas que se tornam sem sentido a longo prazo, e isso se deve em parte à flexibilidade do C ++ em resolver o mesmo problema com muitos recursos de linguagem diferentes (modelos, OOP, procedurais, Modelos RTTI, OOP +, sobrecarga, embutimento).
Eu terminei dois seminários de 4 horas sobre software embarcado em C ++ pelo guru do C ++, Scott Meyers. Ele apontou algumas coisas sobre modelos que eu nunca considerei antes e quanto mais elas podem ajudar a criar código crítico de segurança. O ponto principal é que você não pode ter código morto em software que precisa atender a requisitos rigorosos de código crítico de segurança. Os modelos podem ajudá-lo a fazer isso, pois o compilador cria apenas o código necessário ao instanciar modelos. No entanto, é preciso tornar-se mais instruído em seu uso para projetar corretamente esse recurso, mais difícil de ser realizado em C, porque os vinculadores nem sempre otimizam o código morto.
Scott Meyers é um grande defensor de modelos e uso criterioso de inlining, e devo dizer que ainda estou cético em ser entusiasmado com modelos. Eu costumo me afastar deles, mesmo que ele diga que eles devem ser aplicados apenas quando se tornarem a melhor ferramenta. Ele também enfatiza que o C ++ fornece as ferramentas para criar interfaces realmente boas, fáceis de usar corretamente e que dificultam o uso errado. Novamente, essa é a parte mais difícil. É preciso chegar a um nível de domínio em C ++ antes que você possa saber como aplicar esses recursos da maneira mais eficiente possível para ser a melhor solução de design.
O mesmo vale para OOP. No mundo incorporado, você deve se familiarizar com o tipo de código que o compilador vai cuspir para saber se pode lidar com os custos de tempo de execução do polimorfismo em tempo de execução. Você também deve estar disposto a fazer medições para provar que seu projeto atende aos requisitos de prazo. Essa nova classe InterruptManager tornará minha latência de interrupção muito longa? Existem outras formas de polimorfismo que podem se encaixar melhor no seu problema, como o polimorfismo em tempo de link, que C também pode fazer, mas o C ++ pode fazer através do padrão de design Pimpl (ponteiro opaco) .
Eu digo o suficiente para dizer que o C ++ tem seu lugar no mundo incorporado. Você pode odiar tudo o que quiser, mas não vai embora. Ele pode ser escrito de uma maneira muito eficiente, mas é mais difícil aprender como fazê-lo corretamente do que com C. Às vezes, pode funcionar melhor que C na solução de um problema e, às vezes, na expressão de uma interface melhor, mas, novamente, você precisa eduque-se e não tenha medo de aprender como.
fonte
C ++ é absolutamente adequado para sistemas embarcados. Agora uso a presença / ausência de boas ferramentas de desenvolvimento (ou a falta delas) como meu principal critério para usar ou não um microprocessador específico.
Áreas de C ++ que são boas de usar em sistemas incorporados porque possuem baixos custos de recursos:
Áreas OK:
Áreas a não usar, principalmente por causa da sobrecarga de tempo de execução que é inaceitável em pequenos sistemas:
fonte
foo
chamadasbar
dentro de um blocotry
/ criam alguns objetos e chamadas , o que gera uma exceção, o sistema precisa, de alguma forma, chamar os destruidores dos objetos criados antes de retornar o controle . A menos que as exceções sejam completamente desabilitadas, não haverá como saber se pode lançar alguma e, portanto, deve incluir código extra para permitir essa possibilidade. Eu gostaria de ver uma variação do C ++ com "exceções verificadas" para lidar com isso; se rotinas que poderiam permitir que exceções escapem ... #catch
bar
boz
bar
foo
bar
boz
add r15,r14,#2
vez demov r15,r14
; para sair por exceçãoldrhs r0,[r14] / add r15,r14,r0
. Custo de ciclo zero para a saída normal e sem restrições de estrutura de pilha.Sim, C ++ é certamente adequado para sistemas embarcados. Primeiro, vamos esclarecer alguns conceitos errados sobre a diferença entre C e C ++:
Em um micro incorporado, você sempre precisará usar linguagens de alto nível com cuidado se estiver preocupado com as restrições de tempo ou espaço. Por exemplo, muitos MCUs não lidam bem com ponteiros e, portanto, são muito ineficientes ao usar a pilha. Isso significa que você deve ter cuidado ao passar variáveis para funções, usando matrizes e ponteiros e recursão. Uma linha simples de C como:
pode gerar cerca de 4 páginas de instruções, dependendo da natureza dessas variáveis.
Sempre que você estiver usando qualquer idioma de alto nível e estiver preocupado com as restrições de tempo e espaço, precisará saber como cada recurso desse idioma se traduz em instruções de máquina no seu MCU (pelo menos, todos os recursos que você usa). Isso é verdade para C, C ++, Ada, qualquer que seja. Provavelmente todos os idiomas conterão recursos que não são traduzidos eficientemente em pequenas MCUs. Sempre verifique as listas de desmontagem para garantir que o compilador não esteja gerando resmas de instruções para algo trivial.
C é adequado para MCUs incorporadas? Sim, desde que você fique de olho no código gerado.
O C ++ é adequado para MCUs incorporadas? Sim, desde que você fique de olho no código gerado.
Eis por que acho que o C ++ é melhor que o C, mesmo em MCUs de 8 bits: O C ++ fornece suporte aprimorado para:
Nenhum desses recursos é mais pesado que os recursos típicos de C.
À medida que você move MCUs de 16 ou 32 bits, começa a fazer sentido usar recursos mais pesados de C (pilha, pilha, ponteiros, matrizes, printf etc.) Da mesma forma, um MCU mais poderoso é apropriado. para usar recursos mais pesados do C ++ (pilha, pilha, referências, STL, novo / excluir).
Portanto, não há necessidade de estremecer ao pensar em C ++ em um PIC16. Se você conhece seu idioma e seu MCU corretamente, saberá como usá-los de maneira eficaz juntos.
fonte
a[i] = b[j] * c[k];
pode gerar cerca de 4 páginas de instruções, dependendo da natureza dessas variáveis." Se o seu MCU / compilador faz isso, é porque você está usando alguma CPU hobbyista de garagem dos anos 80.Eu sempre acho esses debates divertidos de ler. Não tanto para a discussão intelectual sobre os prós e contras dos vários idiomas disponíveis, mas porque geralmente você pode identificar a posição de alguém no tópico com base em seu trabalho / experiência / área de interesse. Está aí em cima, com os argumentos de "otimização prematura", onde os principais especialistas em CS e os programadores de manutenção citam Knuth à esquerda e à direita e aqueles que trabalham no mundo real onde questões de desempenho acham que são loucos (sou membro do último grupo) para ser justo).
No final do dia, você pode desenvolver um excelente software em C ou C ++ ou inserir a linguagem aqui . Tudo se resume aos recursos do desenvolvedor, não ao idioma. Ser um especialista em um idioma geralmente é necessário apenas se você escolheu o idioma errado e agora precisa se empenhar para resolver seu problema. Na maioria dos casos, essas são as únicas situações em que você precisa mergulhar em recursos ou compiladores obscuros truques para atingir o objetivo.
Costumo ouvir as pessoas iniciarem esses argumentos como "sou especialista na linguagem X e blá blá". Sinceramente, imediatamente desacredito essas pessoas porque, na minha opinião, elas já abordaram o problema pelo ângulo errado e tudo o que foi contaminado pelo desejo de usar sua ferramenta para resolver o problema e mostrar como é "legal".
Costumo observar os desenvolvedores escolherem primeiro um conjunto de ferramentas e tentarem resolvê-lo em segundo lugar, o que está completamente errado e resulta em soluções ruins.
Como mencionei em um comentário para outra resposta, essas guerras de linguagem frequentemente se baseiam em argumentar que a linguagem X permite que o programador faça coisas mais idiotas. Embora seja divertido ler, todas essas declarações realmente significam é que você tem um problema ao contratar bons desenvolvedores e precisa resolver esse problema diretamente, em vez de tentar ajudar a situação, continuando a contratar maus desenvolvedores e escolhendo ferramentas para que eles possam fazer o mínimo possível. dano possível.
Na minha opinião, bons desenvolvedores, sejam eles de software ou hardware, pesquisam o problema, arquitetam uma solução e encontram as ferramentas que lhes permitem expressar a solução da "melhor maneira". Não importa se a ferramenta necessária é algo que você nunca usou antes, depois de usar 3-4 ferramentas de idiomas / desenvolvimento para projetos que escolhem uma nova ferramenta que tenha um impacto mínimo no tempo de desenvolvimento.
Obviamente, 'melhor caminho' é um termo subjetivo e também precisa ser definido na fase de pesquisa. É preciso considerar uma infinidade de questões: desempenho, facilidade de expressão, densidade de código etc. com base no problema em questão. Não incluí a manutenção nessa lista por um motivo, não me importo com o idioma que você escolher, se você escolheu a ferramenta adequada e gastou um tempo para entender o problema, isso deve vir "de graça". A manutenção difícil do código geralmente resulta da escolha da ferramenta errada ou de uma estrutura de sistema ruim; isso resulta em uma bagunça hacky feia para fazê-lo funcionar.
Reivindicar qualquer idioma é "melhor" do que qualquer outro é tolo sem definir um problema de interesse específico. Uma abordagem orientada a objetos nem sempre é melhor que uma abordagem funcional. Existem alguns problemas que se prestam muito bem a um paradigma de design orientado a objetos. Há muitos que não. A mesma afirmação pode ser feita sobre muitos recursos de linguagem que as pessoas parecem gostar de usar.
Se você está gastando mais de 20% do seu tempo em um problema de digitação de código, provavelmente está produzindo um sistema muito ruim ou tem desenvolvedores muito ruins (ou ainda está aprendendo). Você deve gastar a maior parte do seu tempo antecipadamente diagramando o problema e determinando como várias partes do aplicativo interagem. Colocar um grupo de desenvolvedores talentosos em uma sala com uma placa de marcador e um problema para resolver e dizer a eles que não têm permissão para escrever nenhum código ou escolher nenhuma ferramenta até que se sintam confortáveis com todo o sistema fará mais para melhorar a qualidade do produção e velocidade de desenvolvimento do que escolher qualquer nova ferramenta quente garantida para melhorar o tempo de desenvolvimento. (procure o desenvolvimento scrum como uma referência para o oposto polar ao meu argumento)
Muitas vezes, a triste realidade é que muitas empresas só podem medir o valor de um desenvolvedor pelo número de linhas escritas ou vendo 'saída tangível'. Eles veem as 3 semanas em uma sala com um quadro de marcadores como uma perda de produtividade. Os desenvolvedores geralmente são forçados a acelerar o estágio de "pensamento" do desenvolvimento ou são forçados a usar uma ferramenta definida por algum problema político da empresa: "O irmão do meu chefe trabalha para a IBM, para que possamos usar apenas suas ferramentas", esse tipo de lixo . Ou pior, você obtém um conjunto de requisitos em constante mudança da empresa, porque eles não são capazes de fazer uma pesquisa de mercado adequada ou não entendem o impacto das mudanças no ciclo de desenvolvimento.
Desculpe por estar um pouco fora do tópico com este discurso retórico, tenho opiniões bastante fortes sobre esse tópico.
fonte
Qualquer idioma pode ser adequado para um sistema incorporado. Incorporado significa apenas: parte de um aparelho maior, em oposição a um computador de uso livre.
A pergunta tem mais relevância quando solicitada por um sistema (difícil) em tempo real ou de recursos limitados .
Para um sistema em tempo real, o C ++ é uma das linguagens mais altas que ainda é apropriada na programação de restrições de tempo rigorosas. Com exceção do uso de heap (operador livre), ele não possui construções com tempo de execução indeterminado, para que você possa testar se o seu programa atende aos requisitos de tempo e, com um pouco mais de experiência, pode até prever. Evidentemente, o uso de heap deve ser evitado, embora o novo operador ainda possa ser usado para alocação única. As construções que o C ++ oferece sobre o C podem ser bem utilizadas em um sistema incorporado: OO, exceções, modelos.
Para sistemas com recursos muito limitados (chips de 8 bits, menos de alguns Kb de RAM, sem pilha acessível), o C ++ completo pode ser inadequado, embora ainda possa ser usado como um 'C melhor'.
Eu acho lamentável que Ada pareça ser usado apenas em alguns nichos. De muitas maneiras, é um Pascal ++, mas sem o ônus de ser compatível com uma linguagem que já era uma bagunça séria para começar. (editar: a bagunça séria é, naturalmente, C. Pascal é uma linguagem bonita, mas um tanto impraticável.)
==================================================== ==============
EDIT: Eu estava digitando uma resposta para a nova pergunta ("Em quais casos o C ++ é necessário quando estamos programando microcontroladores"?) Que foi fechado com referência a esta, então adicionarei o que escrevi:
Nunca existe uma razão absoluta para o uso de qualquer linguagem de programação, mas pode haver argumentos que têm mais ou menos peso em uma situação específica. Discussões sobre isso podem ser encontradas em muitos lugares, com posições que variam de "nunca use C ++ para um microcontrolador" a "sempre use C ++". Eu sou mais com a última posição. Posso dar alguns argumentos, mas você terá que decidir por si próprio quanto peso eles têm em uma situação específica (e em que direção).
Meu blog tem alguns escritos sobre o uso de C ++ em pequenos sistemas (= microcontroladores).
fonte
Na minha experiência, o C ++ geralmente não é adequado para pequenos sistemas embarcados. Com o que quero dizer, microcontroladores e dispositivos sem SO.
Muitas técnicas de C ++ OOP contam com alocação dinâmica de memória. Isso geralmente está ausente em pequenos sistemas.
STL e Boost realmente demonstram o poder do C ++, ambos são enormes em tamanho.
O C ++ incentiva o programador a abstrair a máquina, onde em sistemas restritos ela deve ser adotada.
No ano passado, eu levei um produto comercial de desktop remoto para telefones móveis. Foi escrito em C ++ e rodou em Windows, Linux e OSX. Mas, dependia bastante de STL, memória dinâmica e exceções de C ++. Para rodar em ambientes WinCE, Symbian e sem SO, uma reescrita em C era a opção mais segura.
fonte
Espero acrescentar mais luz do que calor a essa discussão sobre C ++ em sistemas bare metal e com recursos limitados.
Problemas em C ++:
As exceções são especialmente um problema de RAM, pois o "buffer de emergência" necessário (onde a exceção de falta de memória ocorre, por exemplo) pode ser maior que a RAM disponível e certamente é um desperdício para os microcontroladores. Para mais informações, consulte n4049 e n4234 . Eles devem ser desativados (que atualmente é um comportamento não especificado, portanto, certifique-se e nunca jogue). Atualmente, o SG14 está trabalhando em melhores maneiras de fazer isso.
RTTI provavelmente nunca vale a pena a sobrecarga, deve ser desativado
Compilações grandes de depuração, embora isso não seja um problema no desenvolvimento clássico de área de trabalho, se a depuração não couber no chip, pode ser um problema. O problema surge do código de modelo ou de chamadas de funções extras adicionadas para maior clareza. Essas chamadas de funções extras serão removidas novamente pelo otimizador e a clareza ou flexibilidade adicional pode ser uma grande vantagem; no entanto, nas compilações de depuração, isso pode ser um problema.
Alocação de pilha. Embora o STL permita o uso de alocadores personalizados, isso pode ser complexo para a maioria dos programadores. A alocação de heap não é determinística (ou seja, não é em tempo real) e a fragmentação pode levar a situações inesperadas de falta de memória, apesar de ter trabalhado nos testes. A manutenção de livros necessária à pilha para controlar o espaço livre e o tamanho variável pode ser um problema com objetos pequenos. Geralmente é melhor usar a alocação de pool (tanto em C quanto em C ++), mas isso pode ser anormal para os programadores de C ++ que costumavam usar apenas o heap.
O polimorfismo de tempo de execução e outras chamadas indiretas geralmente são um grande problema de desempenho, o problema geralmente é maior porque o otimizador não pode ver através deles mais do que a busca e o salto reais para o endereço. Chamadas indiretas devem ser evitadas por esse motivo em C e C ++, onde, como em C ++, elas estão mais arraigadas na cultura (e são bastante úteis em outros domínios).
A interface implícita com o clib pode ser problemática. Pode ser contra-intuitivo que os problemas de clib estejam na categoria C ++, mas o problema surge do compartilhamento implícito de recursos em ambientes simultâneos (o compartilhamento é mais explícito em C). O uso da implementação comum do newLib costuma arrastar muito inchaço, o que geralmente não é necessário nos UCs, por outro lado, o newLibNanno não é reentrante, portanto, o acesso a ele deve ser serializado (simplificando demais aqui). Isso também é um problema para C, mas o acesso é mais explícito. Como regra geral, não se deve essencialmente usar nada do namespace std no contexto ISR, a menos que você tenha certeza de que não acessa o estado no clib de alguma forma (errorno ou o heap, por exemplo). Também é importante se você estiver usando threads (prefiro o RTC) para substituir new e delete para sincronizar o acesso ao malloc e ao free.
Em conclusão, o C ++ tem alguns problemas, mas eles são essencialmente todos corrigíveis ou evitáveis.
Agora para C, aqui o problema é de ordem superior. Eu não tenho a capacidade sintática em C para abstrair as coisas de uma maneira que eu possa executar otimização ou verificar invariantes em tempo de compilação. Portanto, não consigo encapsular adequadamente as coisas de uma maneira que o usuário não precise saber como elas funcionam para usá-las e a maior parte da minha detecção de erros é feita em tempo de execução (o que não é apenas tarde demais, mas também aumenta o custo). Essencialmente, a única maneira de ser genérico em C é através dos dados, passo uma string de formato para printf ou scanf, que é avaliada em tempo de execução, por exemplo. É então difícil para o compilador provar que não estou usando algumas das opções que são teoricamente possíveis quando transmitidas aos dados corretos, o que significa geração potencial de código morto e perda de potencial de otimização.
Eu sei que posso estar desencadeando uma tempestade de merda aqui, mas minha experiência em microcontroladores de 32 bits é que, em uma comparação de maçãs com maçãs, C e C ++, ambos escritos por especialistas (como em C ++ potencialmente altamente modelado), o C ++ é a linguagem muito mais eficiente assim que possível. qualquer coisa precisa ser genérica (como em qualquer biblioteca) e é essencialmente equivalente em casos não genéricos. Também é mais fácil para um iniciante aproveitar o conhecimento de um implementador de biblioteca especializado em C ++.
Ao mesmo tempo, existem realmente poucas funções para as quais não posso passar dados incorretos, assim que a entrada não é um int, mas uma
something
para a qual por acaso estou usando um int como método de representação, então existe um potencial para obtê-lo. errado (passe um valor inválido ou um 'otherThing' em vez de um 'algo'). Em C, meu único método de verificar se o usuário entendeu errado é em tempo de execução. No C ++, tenho a capacidade de executar algumas verificações, nem todas, mas algumas verificações em tempo de compilação, que são gratuitas.No final do dia, uma equipe C é geralmente tão poderosa quanto seu programador mais fraco e o benefício do código resultante tem um multiplayer de 1 ou uma penalidade de desempenho. O que quero dizer com isso é que é alto desempenho para um e apenas um trabalho único em um ambiente único de decisões de design exclusivas ou é genérico o suficiente para ser usado em vários ambientes (outro microcontrolador, outra estratégia de gerenciamento de memória, outra latência vs. trade-offs etc., etc.), mas tem um custo de desempenho inerente.
Em C ++, as coisas podem ser encapsuladas por especialistas e usadas em muitos ambientes onde a geração de código de tempo de compilação se adapta à tarefa específica e a verificação estática impede que os usuários façam coisas estúpidas a custo zero. Aqui, temos muito menos trocas entre ser genérico e ser rápido e, portanto, do ponto de vista do custo versus benefício, são a linguagem mais eficiente, segura e produtiva.
É uma crítica válida que ainda haja uma grande escassez de boas bibliotecas C ++ para incorporação, isso pode levar a decisões pragmáticas de usar principalmente C em um compilador C ++. As decisões de usar apenas C em um projeto são essencialmente orientadas ideologicamente, por necessidade de suporte legado ou por uma admissão de que a equipe não é disciplinada o suficiente para evitar um conjunto muito seleto de coisas estúpidas que se pode fazer em C ++, mas não em C e ao mesmo tempo disciplinado o suficiente para não fazer nada do conjunto muito maior de coisas estúpidas contra as quais não se pode proteger em C, mas em C ++.
fonte
Minha formação: acabei de sair da escola com os antigos programadores do Bell Labs; trabalha há 3 anos, 2 no projeto de pesquisa de graduação; aquisição de dados / controle de processo no VB.NET. Passou 1,5 anos trabalhando em um aplicativo de banco de dados corporativo no VB6. Atualmente trabalhando no projeto de PC embarcado com 2 GB de armazenamento, 512 MB de RAM, CPU x86 de 500 MHz; vários aplicativos executados simultaneamente em C ++ com um mecanismo IPC no meio. Sou jovem
Minha opinião: acho que o C ++ pode funcionar efetivamente, considerando o ambiente que escrevi acima . É certo que o desempenho difícil em tempo real não é um requisito para o aplicativo em que estou, e em alguns aplicativos incorporados, isso pode ser um problema. Mas aqui estão as coisas que aprendi:
C ++ é fundamentalmente diferente de C (ou seja, não há C / C ++). Enquanto tudo que é válido C é válido C ++, C ++ é uma linguagem muito diferente e é preciso aprender a programar em C ++, não em C, para usá-lo efetivamente em qualquer situação. No C ++, você precisa programar orientado a objetos, não processualmente e não um híbrido dos dois (grandes classes com muitas funções). Em geral, você deve se concentrar em criar turmas pequenas com poucas funções e compor todas as turmas pequenas em uma solução maior. Um dos meus colegas de trabalho me explicou que eu costumava programar proceduralmente em objetos, o que é uma grande bagunça e difícil de manter. Quando comecei a aplicar mais técnicas orientadas a objetos, descobri que a manutenção / legibilidade do meu código havia aumentado.
O C ++ fornece recursos adicionais na forma de desenvolvimento orientado a objetos que podem fornecer uma maneira de simplificar o código para facilitar a leitura / manutenção . Sinceramente, não acho que exista muita melhoria no desempenho / eficiência do espaço em fazer POO. Mas acho que a OOP é uma técnica que pode ajudar a dividir um problema complexo em vários pequenos pedaços. E isso é útil para as pessoas que trabalham no código, um elemento desse processo que não deve ser ignorado.
Muitos argumentos contra o C ++ estão relacionados principalmente à alocação dinâmica de memória. C também tem esse mesmo problema. É possível escrever um aplicativo orientado a objetos sem usar memória dinâmica, embora um dos benefícios do uso de objetos seja que você pode alocar essas coisas dinamicamente de maneira fácil. Assim como em C, você precisa ter cuidado com o gerenciamento de dados para reduzir vazamentos de memória, mas a técnica RAII simplifica isso em C ++ (faça com que a memória dinâmica seja destruída automaticamente, encapsulando-a em objetos). Em alguns aplicativos, onde cada local de memória conta, isso pode ser muito selvagem e confuso para gerenciar.
EDITAR:
fonte
Sim, o problema com o C ++ é o aumento da área de cobertura do código.
Em alguns sistemas, você está contando bytes e, nesse caso, terá que aceitar um custo de execução que, próximo aos limites de seus sistemas, aumentará o custo de desenvolvimento de C.
Mas, mesmo em C, para um sistema bem projetado, você precisa manter tudo encapsulado. Sistemas bem projetados são difíceis e o C ++ oferece aos programadores um lugar para um método de desenvolvimento muito estruturado e controlado. Há um custo para aprender POO e, se você quiser mudar, aceita muito; em muitos casos, a gerência prefere continuar com C e não pagar o custo, pois é difícil medir os resultados de um comutador que aumenta a produtividade. Você pode ver um artigo do guru de sistemas embarcados Jack Ganssle aqui .
Gerenciamento dinâmico de memória é o diabo. Na verdade, o diabo é de roteamento automático, o gerenciamento dinâmico de memória funciona muito bem em um PC, mas você pode esperar reiniciar um PC a cada poucas semanas, pelo menos. Você descobrirá que, como um sistema incorporado continua em funcionamento por 5 anos, o gerenciamento dinâmico de memória pode realmente ser estragado e realmente começar a falhar. Ganssle discute coisas como pilha e pilha em seu artigo.
Existem algumas coisas em C ++ que são mais propensas a causar problemas e usam muitos recursos, remover o gerenciamento de memória dinâmica e os modelos são grandes etapas para manter a pegada de C ++ mais próxima da pegada de C. Isso ainda é C ++, você não precisa de dinâmica gerenciamento de memória ou modelos para escrever um bom C ++. Não percebi que eles removeram exceções, considero as exceções uma parte importante do meu código que removo na versão, mas uso até esse momento. Nos testes de campo, posso fazer com que exceções gerem mensagens para me informar sobre uma exceção que está sendo capturada.
fonte
Eu pensei que esse discurso anti-C ++ de Linus Torvalds era interessante.
Ele não está falando sobre o mundo dos sistemas embarcados, mas sobre o desenvolvimento do kernel Linux. Para mim, a relevância vem disso: o C ++ requer a compreensão de um contexto maior e posso aprender a usar um conjunto de modelos de objetos, não confio em mim para lembrá-los quando precisar atualizar o código em alguns meses.
(Por outro lado, atualmente estou trabalhando em um dispositivo incorporado usando Python (não C ++, mas usando o mesmo paradigma OOP) que terá exatamente esse problema. Em minha defesa, é um sistema incorporado poderoso o suficiente para ser chamado de PC Há 10 anos.)
fonte
Eu acho que outras respostas fizeram um bom argumento para os prós, contras e fatores de decisão, então gostaria de resumir e adicionar alguns comentários.
Para microcontroladores pequenos (8 bits), de jeito nenhum. Você está apenas pedindo para se machucar, não há ganho e você vai abrir mão de muitos recursos.
Para microcontroladores de última geração (por exemplo, 32 bits, 10s ou 100s de MB para RAM e armazenamento) que possuem um sistema operacional decente, é perfeitamente bom e, ouso dizer, até recomendado.
Então a pergunta é: onde está o limite?
Não sei ao certo, mas depois que desenvolvi um sistema para um uC de 16 bits com 1 MB de RAM e 1 MB de armazenamento em C ++, apenas para me arrepender mais tarde. Sim, funcionou, mas o trabalho extra que tive não valeu a pena. Eu tive que ajustá-lo, garantir que coisas como exceções não produzissem vazamentos (o suporte ao OS + RTL era bastante complicado e não confiável). Além disso, um aplicativo OO normalmente faz muitas alocações pequenas, e a sobrecarga de pilha para elas foi outro pesadelo.
Dada essa experiência, eu assumiria que, em projetos futuros, escolherei C ++ apenas em sistemas com pelo menos 16 bits e com pelo menos 16 MB para RAM e armazenamento. Esse é um limite arbitrário e provavelmente varia de acordo com coisas como o tipo de aplicativo, estilos de codificação e idiomas, etc. Mas, dadas as advertências, eu recomendaria uma abordagem semelhante.
fonte
Existem alguns recursos do C ++ que são úteis em sistemas incorporados. Existem outros, como exceções, que podem ser caros e cujos custos nem sempre são aparentes.
Se eu tivesse meus doutores, haveria uma linguagem popular que combinasse o melhor dos dois mundos e incluísse alguns recursos que faltam nos dois idiomas; alguns fornecedores incluem alguns desses recursos, mas não há padrões. Gostaria de ver algumas coisas:
Eu sei que o pai do C ++ não gosta muito de uma versão incorporada do C ++, mas acho que poderia oferecer algumas melhorias consideráveis em relação ao uso de C.
Alguém sabe se algo como o acima está sendo considerado para algum tipo de padrão?
fonte
C ++ é mais do que uma linguagem de programação:
a) É um "melhor" C b) É uma linguagem orientada a objetos c) É uma linguagem que nos permite escrever programas genéricos
Embora todos esses recursos possam ser usados separadamente, os melhores resultados são alcançados quando os três são usados ao mesmo tempo. No entanto, se você escolher apenas um deles, a qualidade do software incorporado aumentará.
a) É um C "melhor"
C ++ é uma linguagem tipificada forte; mais forte que C. Seus programas se beneficiarão desse recurso.
Algumas pessoas têm medo de indicadores. C ++ inclui as referências. Funções sobrecarregadas.
E vale a pena dizer: Nenhum desses recursos ocorreu em programas maiores ou mais lentos.
b) É uma linguagem orientada a objetos
Alguém disse neste post que abstrair a máquina em microcontroladores não é uma boa idéia. Errado! Todos nós, engenheiros embarcados, sempre abstraímos a máquina, apenas com outra sintaxe que a do C ++. O problema que vejo com esse argumento é que alguns programadores não estão acostumados a pensar em objetos, é assim que não vêem os benefícios do OOP.
Sempre que você estiver pronto para usar o periférico de um microcontrolador, é provável que o periférico tenha sido extraído para nós (de você ou de terceiros) na forma do driver do dispositivo. Como eu disse antes, esse driver usa a sintaxe C, como mostra o próximo exemplo (extraído diretamente de um exemplo NXP LPC1114):
/ * Configuração do temporizador para correspondência e interrupção em TICKRATE_HZ * /
Chip_TIMER_Reset (LPC_TIMER32_0);
Chip_TIMER_MatchEnableInt (LPC_TIMER32_0, 1);
Chip_TIMER_SetMatch (LPC_TIMER32_0, 1, (timerFreq / TICKRATE_HZ2));
Chip_TIMER_ResetOnMatchEnable (LPC_TIMER32_0, 1);
Chip_TIMER_Enable (LPC_TIMER32_0);
Você vê a abstração? Portanto, ao usar o C ++ para o mesmo objetivo, a abstração é levada para o próximo nível através do mecanismo de abstração e encapsulamento do C ++, a custo zero!
c) É uma linguagem que nos permite escrever programas genéricos
Os programas genéricos são alcançados por meio de modelos, e os modelos também não têm custos para nossos programas.
Além disso, o polimorfismo estático é alcançado com modelos.
Métodos virtuais, RTTI e exceções.
Há um comprometimento ao usar métodos virtuais: software melhor versus alguma penalidade no desempenho. No entanto, lembre-se de que a ligação dinâmica provavelmente será implementada usando uma tabela virtual (uma matriz de ponteiros de função). Eu fiz o mesmo em C várias vezes (mesmo regularmente), então não vejo as desvantagens em usar métodos virtuais. Além disso, os métodos virtuais em C ++ são mais elegantes.
Por fim, um conselho sobre RTTI e exceções: NÃO OS UTILIZE em sistemas embarcados. Evite-os a todo custo !!
fonte
Meu histórico, incorporado (mcu, pc, unix, outro), em tempo real. Segurança crítica. Eu introduzi um empregador anterior na STL. Eu não faço mais isso.
Algum conteúdo de chama
O C ++ é adequado para sistemas embarcados?
Meh. C ++ é uma dor para escrever e uma dor para manter. C + está bem (não use alguns recursos)
C ++ em microcontroladores? RTOSes? Torradeiras? PCs incorporados?
Mais uma vez eu digo Meh. C + não é tão ruim, mas o ADA é menos doloroso (e isso realmente está dizendo algo). Se você tiver sorte como eu, poderá fazer Java incorporado. O acesso verificado ao array e nenhuma aritmética de ponteiro criam códigos muito confiáveis. Os coletores de lixo no Java incorporado não são a prioridade mais alta, e há escopo de memória e reutilização de objetos; portanto, códigos bem projetados podem ser executados para sempre sem um GC.
OOP é útil em microcontroladores?
Claro que é. O UART é um objeto ..... O DMAC é um objeto ...
Máquinas de estado de objeto são muito fáceis.
O C ++ remove o programador muito longe do hardware para ser eficiente?
A menos que seja um PDP-11, C não é sua CPU. O C ++ era originalmente um pré-processador sobre o C, então Bjarne Stroustrup parava de rir por ter simulações lentas no Simula enquanto estava na AT&T. C ++ não é sua CPU.
Vá buscar um MCU que execute java bytecodes. Programa em Java. Rir dos caras do C.
O C ++ do Arduino (sem gerenciamento dinâmico de memória, modelos, exceções) deve ser considerado como "C ++ real"?
Não. assim como todos os bastardos compiladores C disponíveis para MCU's.
Em quarto lugar, o Java Incorporado ou o ADA Incorporado são padronizados (ish); tudo o mais é tristeza.
fonte
Os sistemas incorporados são projetados para executar alguma tarefa específica, em vez de ser um computador de uso geral para várias tarefas. Um sistema incorporado é uma combinação de hardware e software de computador. C é a mãe de todas as línguas modernas. É um nível baixo, mas oferece uma linguagem completa e lida com todo o tipo de hardware. Portanto, o C / C ++ é uma escolha ideal para o desenvolvimento de software para sistemas embarcados, que é bastante útil para todos os sistemas embarcados. Como sabemos, o C é uma linguagem em desenvolvimento. O UNIX do sistema operacional é escrito em C. Como o desenvolvimento bem-sucedido de software é tão frequentemente sobre a seleção do melhor idioma para um determinado projeto, é surpreendente descobrir que a linguagem C / C ++ se provou adequada para processadores de 8 e 64 bits. ; em sistemas com bytes, kilobytes e megabytes de memória. C tem o benefício da independência do processador, que permite que os programadores se concentrem em algoritmos e aplicativos, em vez de nos detalhes de uma arquitetura de processador específica. No entanto, muitas dessas vantagens se aplicam igualmente a outros idiomas de alto nível. Mas o C / C ++ teve êxito onde muitas outras linguagens falharam?
fonte
<rant>
Eu acho que C ++ é uma linguagem de baixa qualidade em primeiro lugar. Se você deseja usar o OOP, escreva programas Java. O C ++ não faz nada para impor paradigmas de POO, pois o acesso direto à memória está totalmente ao seu alcance para (ab) usar.
Se você possui um MCU, provavelmente está falando de menos de 100kB de memória flash. Você deseja programar em uma linguagem cuja abstração da memória seja: quando declaro uma variável ou uma matriz, ela obtém memória, ponto final; O malloc (também conhecido como palavra-chave "new" em C ++) deve ser mais ou menos proibido de usar em software incorporado, exceto talvez em raras ocasiões uma chamada durante a inicialização do programa.
Inferno, existem (frequentemente) momentos na programação incorporada em que C não é suficientemente baixo, e você precisa fazer coisas como alocar variáveis para registradores e escrever montagem em linha para reforçar suas rotinas de serviço de interrupção (ISRs). Palavras-chave como "volátil" tornam-se muito importantes para entender. Você gasta muito tempo manipulando memória no nível de bits , não no nível de objeto .
Por que você quer se iludir pensando que as coisas são mais simples do que realmente são?
</rant>
fonte