01 julho 2015

Memory Leak / vazamento de memória na programação


Recentemente me deparei com problemas de memory leak no desenvolvimento de uma aplicação para iOS (iPhone/iPad) e foi difícil de resolver e achar a causa do problema. Comentarei um pouco sobre isso.


Memória é um recurso excelente para fazer nossos aplicativos rodarem de acordo com o esperado. Porém, quando falta memória o aplicativo pode fechar inesperadamente. Também conhecido como CRASH.

Em aplicações iOS, que são baseados em linguagem C, trabalhamos com as linguagens Objective-c ou Swift, que normalmente fazem uso de ponteiros e acesso a endereços de memória. Qualquer "vacilada" ou descuido durante a programação, levamos a erros que geram CRASHs.

Memory leak é um tipo de erro muito indesejado e são problemas de memória alocada, mas que na prática, não liberada, ficando acumulada e retida (presa). Assim, se deixar vazamento de memória em algum ponto do programa, o acesso consecutivo a esse ponto vai gerar acúmulo de recursos de memória. O problema ocorre porque o SO não consegue desalocar esse recurso porque ficou retido.

Há várias possíveis razões:

  • variáveis alocadas ficam referenciadas em algum ponto durante a  execução do algoritmo;
  • recursos que consomem mais memória podem ficar retidos em processos Zombis;
  • componentes da plataforma consomem recursos e não são fortemente liberados (ex. UIImagePickerController - iOS / manipular a câmera que tira as fotos possui memory leak);
  • uso de propriedades de componentes visuais com tipo "strong" pode reter memória (em iOS/MacOS...);
  • uso de bibliotecas ou modificações nesses componentes sem analisar essa questão, etc.


Como evitar vazamento de memória


Uma forma interessante é utilizar ferramentas de Profiling. No iOS temos o "instruments", que é um conjunto de ferramentas que podem ser usadas para analisar a execução do programa para avaliar graficamente e os dados estatísticos, onde estão os pontos errados. Identificar esses pontos permitirá avaliar o código melhor e tomar decisões para corrigir as falhas.

Uma forma eficiente que aprendi, quando temos leaks identificados, mas sem saber a causa, pode-se ir comentando funcionalidades chaves e rodar novamente o Profiling. Se ocorrer mudanças significativas para melhor, significa que o provável memory leak está no ponto comentado, caso contrário, continue comentando códigos e rodando o analisador novamente até que encontre o "vilão".