Estou trabalhando em um aplicativo incorporado médio em C usando técnicas semelhantes a OO. Minhas "classes" são módulos .h / .c usando estruturas de dados e estruturas de ponteiros de função para emular encapsulamento, polimorfismo e injeção de dependência.
Agora, seria de esperar que uma myModule_create(void)
função viesse com uma myModule_destroy(pointer)
contraparte. Mas, quando o projeto está sendo incorporado, os recursos que são instanciados realisticamente nunca devem ser liberados.
Quero dizer, se eu tiver 4 portas seriais UART e criar 4 instâncias UART com os pinos e configurações necessários, não há absolutamente nenhuma razão para querer destruir o UART # 2 em algum momento durante o tempo de execução.
Então, seguindo o princípio YAGNI (você não vai precisar disso), devo omitir os destruidores? Isso me parece extremamente estranho, mas não consigo pensar em uma utilidade para eles; os recursos são liberados quando o dispositivo é desligado.
fonte
myModule_create(void)
função? Você pode apenas codificar as instâncias específicas que você espera usar na interface que você expõe.Respostas:
Glampert está certo; não há necessidade de destruidores aqui. Eles apenas criariam inchaço no código e uma armadilha para os usuários (o uso de um objeto depois que seu destruidor é chamado é um comportamento indefinido).
No entanto, você deve ter certeza de que realmente não há necessidade de descartar os objetos. Por exemplo, você precisa ter um objeto para um UART que não esteja em uso no momento?
fonte
A maneira mais fácil que encontrei para detectar vazamentos de memória é poder sair corretamente do seu aplicativo. Muitos compiladores / ambientes fornecem uma maneira de verificar a memória que ainda está alocada quando o aplicativo sai. Se não for fornecido, geralmente há uma maneira de adicionar algum código antes de sair, o que pode ser compreendido.
Portanto, eu certamente forneceria construtores, destruidores e lógica de desligamento mesmo em um sistema incorporado que "teoricamente" nunca deveria sair para facilitar a detecção de vazamento de memória sozinho. Atualmente, a detecção de vazamento de memória é ainda mais importante se o código do aplicativo nunca deve sair.
fonte
No meu desenvolvimento, que faz uso extensivo de tipos de dados opacos para promover uma abordagem semelhante ao OO, também lutei com essa questão. No começo, decidi eliminar o destruidor da perspectiva do YAGNI, bem como da perspectiva do "código morto" do MISRA. (Eu tinha bastante espaço de recursos, isso não era uma consideração.)
No entanto ... a falta de um destruidor pode dificultar os testes, como nos testes automatizados de unidade / integração. Convencionalmente, cada teste deve suportar uma configuração / desmontagem para que os objetos possam ser criados, manipulados e destruídos. Eles são destruídos para garantir um ponto de partida limpo e sem manchas para o próximo teste. Para fazer isso, a classe precisa de um destruidor.
Portanto, na minha experiência, o "não é" no YAGNI acaba sendo um "são" e acabei criando destruidores para todas as classes, achando que precisaria ou não. Mesmo que eu tenha pulado os testes, pelo menos um destruidor projetado corretamente existe para o pobre slob que me segue terá um. (E, com um valor muito menor, torna o código mais reutilizável, pois pode ser usado em um ambiente onde seria destruído.)
Enquanto isso endereça YAGNI, ele não endereça código morto. Para isso, acho que uma macro de compilação condicional, como #define BUILD_FOR_TESTING, permite que o destruidor seja eliminado da compilação de produção final.
Fazendo desta maneira: você tem destruidor para teste / reutilização futura e satisfaz os objetivos de design do YAGNI e as regras "sem código morto".
fonte
Você poderia ter um destruidor não operacional, algo como
depois defina o destruidor de
Uart
talvez usar(adicione o elenco adequado, se necessário)
Não se esqueça de documentar. Talvez você queira mesmo
Como alternativa, caso especial no código comum chamando destruidor o caso quando a função do ponteiro destruidor é
NULL
evitar chamá-lo.fonte