Você sabe para que servem os arquivos PDB? Se as enquetes informais que faço durante meus treinamentos servem de indicador, então arriscaria dizer que a maioria dos desenvolvedores .NET não sabem.
Invariavelmente, as respostas que recebo à pergunta-título deste post variam entre uma das duas opções abaixo:
“Servem para poder debugar [sic] os programas. Por isso eles só são gerados quando compilamos em modo Debug.”
“Não servem para nada. Ou melhor, servem para ser apagados assim que são criados.”
Bom, é hora de explicar isso um pouco melhor.
A história por trás do PDB
Arquivos PDB (acrônimo de Programa Database) foram criados pela Microsoft para facilitar o processo de depuração de aplicações C++.
O grande desafio de se depurar uma aplicação C++ (ou qualquer outra linguagem que seja compilada para código nativo) é que, uma vez gerado o código nativo (seja um EXE ou uma DLL), tudo o que temos são instruções opcodes (instruções de baixo nível) e ponteiros. Em outras palavras, nada que nos permita executar um programa linha-a-linha e inspecionar o valor de suas variáveis.
Para uma execução linha-a-linha, como a que temos no Visual Studio, precisaríamos basicamente de:
- Uma lista com os nomes de variáveis e seus endereços correspondentes na memória. Assim, quando o depurador encontrasse um ponteiro de memória, ele saberia a que variável aquele endereço corresponde;
- Uma outra lista com os nomes dos arquivos de código-fonte, seus números de linha e o endereço de memória correspondente. Assim, quando o depurador fosse executar uma instrução num determinado endereço de memória, saberia a qual linha ele corresponde e poderia exibi-la na tela.
O compilador tem condições de gerar todas essas informações. A dúvida era: Onde armazena-las? Guardar essas informações dentro do próprio arquivo binário não faria sentido, afinal geraria um overhead desnecessário. Os arquivos ficariam muito grandes, recheados de informações que só seriam úteis durante uma sessão de depuração. Veio daí a ideia de criar um arquivo auxiliar para armazenar essas informações: o arquivo PDB.
Introduzidos juntamente com o Visual C++ 1.0, os arquivos PDB armazenam as seguintes informações (metadados) de um binário C++:
- Símbolos públicos (tipicamente todas as funções, variáveis estáticas e variáveis globais);
- Uma lista dos objetos que são responsáveis por seções de código no arquivo executável;
- Informações de Frame-pointer omission (FPO);
- Informações sobre nome e tipo de dados para variáveis locais e estruturas de dados;
- Informações sobre nome de arquivo-fonte e número de linha.
Com isso, depurar código C++ ficou muito mais fácil. O Visual Studio tem um banco de dados repleto de informações detalhadas sobre nossos arquivos executáveis, sem que isso gere um overhead desnecessário ao coloca-los em produção.
Arquivos PDB e o .NET
Arquivos executáveis em .NET (os assemblies) são completamente diferentes de suas contrapartes em código nativo. Ainda que tenham as mesmas extensões (EXE e DLL), sua estrutura interna é bem diferente. Não apenas pela linguagem (MSIL vs. código nativo) mas principalmente pela presença de metadados. Assemblies .NET são ricos em metadados. São eles que permitem, por exemplo, que possamos fazer reflexão (reflection) sobre nossos objetos. Ou seja, grande parte das informações que um PDB nativo precisa armazenar ao compilarmos aplicações C++ já está presente dentro do próprio assembly .NET, sendo portanto redundantes. Para o .NET, os arquivos PDB contêm apenas:
- Informações sobre nomes e endereços de variáveis locais; e
- Informações sobre nome de arquivo-fonte e número de linha.
Parece pouca coisa, né? Mas é fácil perceber a diferença entre a presença e a ausência de um arquivo PDB. Mas antes de mais nada, conheça nosso pequeno aplicativo-teste:
Agora vamos executa-lo duas vezes. Na primeira manteremos o arquivo PDB junto ao executável. Já na segunda, excluiremos o arquivo antes de executar nosso aplicativo.
Veja as duas mensagens de erro e seus respectivos stack traces. Note como, na ausência do PDB (na segunda figura), não é possível saber as linhas dos métodos na pilha:
E isso não tem nada a ver com o aplicativo ter sido compilado em modo Debug ou Release. Veja abaixo que, mesmo compilando em modo Release (repare no caminho na barra de títulos da janela), o nome de arquivo e a linha são exibidos:
Agora, a parte mais legal: a utilidade dos PDBs vai muito além do F5 de uma típica sessão de depuração. Os PDBs se mostram realmente úteis quando usados para diagnosticar problemas em… produção!
PDBs em Produção
Existem várias ferramentas que ajudam a diagnosticar problemas em produção: desde o tradicional crash dump até os modernos IntelliTrace e System Center Operations Manager (SCOM) APM. Dessa forma, exceções sendo disparadas em produção poderiam ser capturadas em produção e corrigidas em desenvolvimento, sem necessidade de intervenção direta do time de desenvolvimento.
Entretanto, se você não tiver os PDBs, seu crash dump ou seu log do IntelliTrace serão praticamente inúteis, pois você não conseguirá correlacionar o binário em produção com o código-fonte em desenvolvimento.
Isso significa que, quando eu colocar uma aplicação em produção, devo colocar os PDBs em produção também? Bem, a resposta não é tão óbvia assim.
Vamos por partes:
- Os arquivos PDB são importantes?
Sim, muito! Para todos os efeitos, considere que os arquivos PDB são tão importantes quanto seus binários EXE e DLL. - Quer dizer que devo sempre manter os PDBs, mesmo quando coloco minha aplicação em produção?
Sim, deve. Mesmo quando compila seu binário em modo Release. - Então devo copiar meus PDBs para o ambiente de produção, junto com os binários, sempre que fizer uma implantação?
É aqui que as coisas começam a ficar um pouco mais confusas. Como já falamos, você deve guardar o PDB. Entretanto ele não deveria ir para a produção. Ele não é útil lá – e além disso pode representar uma vulnerabilidade de segurança, deixando à disposição informações sobre seu código-fonte que deveriam estar disponíveis apenas em desenvolvimento. - Então onde eu guardo meus PDBs se não posso copia-los para produção?
É para isso que você deveria ter um servidor de símbolos (symbol server) em sua empresa.
Servidor de Símbolos
Um servidor de símbolos, apesar do nome pomposo, é simplesmente um compartilhamento de rede onde você armazena e versiona seus PDBs.
Vou falar mais sobre servidores de símbolos – como instalar, configurar e atualizar – mas isso fica para o próximo post.
Um abraço,
Igor
(Post publicado originalmente em http://tshooter.com.br/2013/08/27/para-que-servem-os-arquivos-pdb/)
Igor Abade
Igor Abade V. Leite ([email protected]) é Microsoft MVP (Most Valuable Professional) de Visual Studio ALM desde 2006. Palestrante em diversos eventos da comunidade de desenvolvimento de software (TechEd Brasil, The Developers’ Conference, DevOps Summit Brasil, Agile Brazil, Visual Studio Summit, QCON e outros), é também autor de artigos em revistas e sites como o MSDN Brasil. Desde março de 2011 é um dos sócios da Lambda3, uma consultoria especializada em ALM, desenvolvimento de software e treinamentos. Siga-o no Twitter @igorabade.