Desafio da Semana #1
DESAFIO DA SEMANA
Esses dias fiquei pensando sobre o que poderia colocar no blog, além de artigos técnicos, que pudesse ser interessante. Pensei em técnicas de depuração com WinDbg para código nativo ou gerenciado, mostrar uso de algumas ferramentas de troubleshooting, falar sobre incidentes interessantes que pegamos aqui nos times de escalações, etc... mas uma rápida pesquisa na internet me mostrou que existem blogs aos montes falando sobre esses assuntos. A grande maioria é em inglês, entretanto, para os que não dominam o idioma, com conhecimento de inglês técnico apenas é possível se entender muitas coisas.
Pois bem, me ocorreu de disseminar conhecimento sobre a forma de desafios! Pesquisei sobre isso e não vi blogs que fizessem isso, portanto, creio ser uma forma interessante de se disseminar e compartilhar conhecimento.
A idéia é colocar uma situação fictícia de um cliente que pede seu auxílio. A situação é uma breve descrição dos sintomas apresentados por uma aplicação, o código fonte ou instruções sobre como reproduzir os sintomas e a descrição do seu objetivo.
Portanto como um fictício engenheiro de escalação, seu objetivo será de isolar o problema, propor a devida solução para corrigi-lo e explicar a estratégia utilizada para isolar o problema.
Após uma semana colocarei a resposta e comentarei os posts. As aplicações serão em C, C++, Visual Basic 6, Visual Basic .NET ou C#. O nível de dificuldade será justo pois o objetivo é que para que muitos consigam resolver os problemas. Na verdade, o interessante será observar a estratégia usada para se isolar o problema e a solução proposta, pois diferentes abordagens e soluções poderão ser aplicadas na maioria dos problemas!
Essa abordagem será um modo interessante de compartilharmos conhecimento pois acredito que muitos vão propor estratégias criativas para se isolar o problema ou soluções criativas para corrigi-lo!
Portanto, vamos ao primeiro da série!
DESAFIO DA SEMANA #1
Um cliente contactou você porque uma aplicação C aparenta estar consumindo memória sem nunca liberá-la. Seu objetivo é de certificar que o sintoma é esse mesmo, e, em seguida, identificar o problema causando esse sintoma, propor uma solução (solução prática que exija o mínimo de alterações na aplicação) e descrever as possíveis estratégias para se isolar esse problema.
Nota: Imagine que você tenha que descrever um modo de se identificar o problema de memória que seja válido para essa simples aplicação e para uma grande aplicação com milhares de linhas de código. Esse é o objetivo mais importante desse desafio.
INSTRUÇÕES
Crie uma aplicação console em Visual C++ com nome de MemoryLeak. exe e coloque o seguinte código:
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SINTOMAS: Vazamento de memoria. (memory leak)
//
// OBJETIVO: Isolar o problema causando o memory leak e corrigir a aplicacao.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
_tprintf(_T("Memory Leak Demo\n"));
_tprintf(_T("Pressione alguma tecla para iniciar...\n\n"));
_getch();
for(int i = 0; i < 50; i++)
{
BYTE* pbyAllocated = (BYTE*) malloc (sizeof(BYTE) * (10000 * i));
if(pbyAllocated)
{
_tprintf(_T("Memoria alocada com sucesso!\n"));
}
else
{
_tprintf(_T("Alocacao de memoria falhou...\n"));
}
// Libera memoria
pbyAllocated = NULL;
Sleep(1000);
}
_tprintf(_T("Pressione alguma tecla para finalizar...\n"));
_getch();
return 0;
}
Gere um executável versão Debug ou Release.
Coloque sua resposta aqui no blog no seguinte formato:
SINTOMA
(é um vazamento de memória ou de handle?)
PROBLEMA
(o que está ocasionando o leak?)
SOLUÇÃO
(qual a solução proposta para corrigir o problema?)
ESTRATÉGIA
(qual estratégia você usou para comprovar os sintomas e isolar o problema?)
Na semana que vem colocarei uma resposta para esse desafio, mas sempre que possível estarei lendo os comentários e respondendo eventuais dúvidas.
Até a próxima!
Roberto Farah
Comments
- Anonymous
April 08, 2006
The comment has been removed - Anonymous
April 11, 2006
SINTOMA
A memória utilizada pelo programa está sempre aumentando enquanto o programa está sendo executado e não há evidencias de que a memória está sendo liberada. Provável memory leak.
PROBLEMA
Em C a maior causa de memory leaks é memória sendo alocada com malloc e nunca sendo liberada com free.
SOLUÇÃO / ESTRATÉGIA
Existem várias soluções, desde procurar por todos os mallocs e free (o que pode ser impossivel em aplicações grandes), até usar ferramentas que ajudam na caça aos memory leaks.
O que eu faria em qualquer situação (programando em C) seria criar minhas próprias funções de alocação de desalocação de memória. Na função de alocação eu armazenaria em uma estrutura, informações sobre a memória que está sendo alocada como por exemplo:
- Nome da variável
- Arquivo
- Linha
- Posição da memória alocada (ÓBVIAMENTE)
E armazenaria essas informações numa BSTree ou numa Linked list. (O código de busca não precisa ser muito eficiente porque só vai ser usado em modo debug para diagnosticar o problema).
Na funções de desalocação de memória, usando como chave de busca a posição de memória alocada, basta remover o indice da lista (BSTtree ou Linked List).
Caso necessário poderiamos tb criar um log num arquivo de todas as alocações e desalocações de memória.
Após a criação dessas funções, basta criar MACROS para substituir malloc e free em todo o código para usar as funções e para ativar ou desativar o código de detecção de memory leaks.
Antes do termino do programa, basta checar a lista de alocação de memória e todas os membros dessa lista são memória que deveriam ter sido desalocados e óbviamente não foram. - Anonymous
April 11, 2006
The comment has been removed - Anonymous
April 13, 2006
Ola Pessoal!
Não sei se aqui seria o local apropriado para estar falando sobre isso, mas como se trata de um assunto referente ao blog estou colocando meu post aqui mesmo.
Caso venha estar incomodando ou exista um local adequado para este post peço desculpas ao moderador.
Gostaria apenas de parabenizar o(s) criador (es) deste blog, tanto pelo seu conteúdo de arquivos, tais como dicas, exemplos, discussões e tutoriais, mas também pela brilhante idéia de terem criado o "DESAFIO DA SEMANA", cujo objetivo do mesmo é lançar um desafio aos usuários do blog e que os mesmos possam trazer a solução fazendo com que passemos por situações as quais geralmente não estamos acostumados a passar e nem mesmo a utilizar certas soluções.
Não desenvolvo em linguagem C, porém acompanho todos os dias o blog e leio todos os posts independente da linguagem mencionada.
Terminando então gostaria de mais uma vez pedir desculpas se postei em local errado, mas não poderia deixar de dar minha opinião sobre esta brilhante idéia que os criadores tiveram.
Parabéns a todos os envolvidos e espero que este blog persista para que possamos a cada dia aprender mais com vocês.
Um grande abraço, Biel. - Anonymous
April 13, 2006
Oi pessoal!
Amanha estarei publicando as respostas desse desafio, um novo desafio novo e um artigo sobre DebugDiag.
Aproveito para fazer uns comentarios sobre os posts acima. :)
Primeiro, parabens a todos que responderam! As respostas estao corretas!
Apresentarei, no artigo de respostas, algumas respostas usando os mesmos conceitos.
Danilo e Marcondes usaram uma abordagem reativa que possibilita checar se ha' um potencial memory leak, independente da linguagem de programacao usada, sem necessidade de acesso ao fonte! Usamos muito esse conceito em situacoes reais. Marcelo sugeriu uma abordagem proativa onde o vazamento de memoria seria mostrado pela propria aplicacao, incluindo o local ocasionando o leak! Muito bom! Uma aplicacao que tenha implementado esse conceito evitaria abordagens reativas, economizando tempo de troubleshooting, recursos, etc...
Na pratica costumamos usar ambos os conceitos com aplicacoes que nao tenham mecanismos de prevencao de vazamento de memoria, ou quando suspeitamos que o mecanismo em si tem problemas :) - Agimos reativamente para comprovar o sintoma e identificar a aplicacao responsavel, depois recomendamos acoes proativas para evitar a ocorrencia do sintoma novamente. Explicarei mais sobre isso no artigo de resposta.
Biel, muito obrigado pelo post! Continuarei a postar desafios semanais! O proximo sera em VB 6, depois C#, talvez coloque de Assembly tambem.
Lembrando que o que realmente conta no Desafio da Semana e' a abordagem para isolar determinado problema e a solucao proposta, uma vez que os problemas serao relativamente simples. Minhas respostas nao devem ser tomadas como unicas, na verdade, tanto os modos de se isolar o problema quando, em muitos casos, as solucoes propostas deveriam ser vistas em termos de vantagens e desvantagens, desde que corretas.
Obrigado a todos por participar e fiquem a vontade para sugerir artigos/desafios!
:)
Roberto Farah