Blob Blame History Raw
<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="tooling" xml:lang="pt-BR">

  <info>
    <link type="guide" xref="index#general-guidelines"/>

    <credit type="author copyright">
      <name>Philip Withnall</name>
      <email its:translate="no">philip.withnall@collabora.co.uk</email>
      <years>2015</years>
    </credit>

    <include xmlns="http://www.w3.org/2001/XInclude" href="cc-by-sa-3-0.xml"/>

    <desc>Usando a ferramenta certa para várias tarefas</desc>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Rafael Fontenelle</mal:name>
      <mal:email>rafaelff@gnome.org</mal:email>
      <mal:years>2017</mal:years>
    </mal:credit>
  </info>

  <title>Ferramentas</title>

  <p>Ferramentas de desenvolvimento são muito mais do que um editor de texto e um compilador. O uso correto das ferramentas certas pode facilitar drasticamente a depuração e o rastreamento de problemas complexos com alocação de memória e chamadas de sistema; além de outras coisas. Algumas das ferramentas mais comumente usadas são descritas abaixo; outras ferramentas existem para casos de uso mais especializados e devem ser usados quando apropriado.</p>

  <p>Um princípio geral a se usar quando se está desenvolvendo é sempre ter tantas opções de depuração habilitadas quanto possível, em vez de mantê-las desabilitadas até próximo da data de lançamento. Ao testar o código constantemente com todas as ferramentas de depuração disponível, erros podem ser encontrados desde cedo, antes que eles façam parte do código e, portanto, mais seja difícil de removê-los.</p>

  <p>Na prática, isso significa ter todos os avisos, do compilador e de outras ferramentas, habilitados e definidos para falhar no processo de compilação com um erro se forem emitidos.</p>

  <synopsis>
    <title>Resumo</title>

    <list>
      <item><p>Compile com frequência com um segundo compilador. (<link xref="#gcc-and-clang"/>)</p></item>
      <item><p>Habilite uma seleção grande de avisos de compilador e faça-os falhar. (<link xref="#gcc-and-clang"/>)</p></item>
      <item><p>Use GDB para depurar e passear pelo código. (<link xref="#gdb"/>)</p></item>
      <item><p>Use Valgrind para analisar o uso de memória, erros de memória, cache e desempenho da CPU e erros em threads. (<link xref="#valgrind"/>)</p></item>
      <item><p>Use gcov e lcov para analisar a cobertura de teste de unidade. (<link xref="#gcov-and-lcov"/>)</p></item>
      <item><p>Use sanitizadores de compilador para analisar problemas de memória, thread e comportamentos indefinidos. (<link xref="#sanitizers"/>)</p></item>
      <item><p>Envie para Coverity como um cronjob e elimine erros de análise estática na medida em que eles aparecem. (<link xref="#coverity"/>)</p></item>
      <item><p>Use o analisador estático do Clang e o Tartan regularmente para eliminar localmente erros analisáveis estaticamente</p></item>
    </list>
  </synopsis>

  <section id="gcc-and-clang">
    <title>GCC e Clang</title>

    <p><link href="https://gcc.gnu.org/onlinedocs/gcc/">GCC</link> é o compilador C padrão para Linux. Existe uma alternativa na forma de <link href="http://clang.llvm.org/docs/UsersManual.html">Clang</link>, com funcionalidade comparável. Escolha um (provavelmente GCC) para usar como compilador principal, mas ocasionalmente use o outro para compilar o código, já que os dois detectam um conjunto um pouco diferente de erros e avisos no código. Clang também vem com uma ferramenta de análise estática que pode ser usada para detectar erros no código sem precisar compilá-lo e executá-lo; veja <link xref="#clang-static-analyzer"/>.</p>

    <p>Ambos compiladores devem ser usados com tantos sinalizadores de avisos habilitados quanto possível. Apesar de avisos de compilador de vez em quando fornecerem falsos positivos, a maioria dos avisos legitimamente aponta para problemas no código e, portanto, devem ser corrigidos em vez de ignorados. Uma política de desenvolvimento de habilitar todos sinalizadores de avisos e também especificar o sinalizador <code>-Werror</code> (que torna todos os avisos em fatais para compilação) promove correção de avisos assim que forem introduzidos. Isso ajuda na qualidade do código. A alternativa de ignorar avisos leva a longas sessões de depuração para rastrear erros causados por problemas que teriam sido levantados pelos avisos. Similarmente, ignorar avisos até o fim do ciclo de desenvolvimento para, em um momento posterior, gastar um pedaço de tempo habilitando e corrigindo todos eles é uma perda de tempo.</p>

    <p>Ambos GCC e Clang oferecem suporte a um amplo alcance de sinalizadores de compilador, estando apenas alguns relacionados a um código moderno e multipropósito (por exemplo, outros estão desatualizados e são para alguma arquitetura específica). Encontrar um conjunto razoável de sinalizadores para habilitar pode ser complicado e por isto que a macro <link href="http://www.gnu.org/software/autoconf-archive/ax_compiler_flags.html"> <code>AX_COMPILER_FLAGS</code></link> existe.</p>

    <p><code>AX_COMPILER_FLAGS</code> permite um conjunto consistente de avisos de compilador e também testa se o computador oferece suporte a cada sinalizador antes de habilitá-lo. Isso conta para diferenças no conjunto de sinalizadores aos quais GCC e Clang oferecem suporte. Para usá-lo, adicione <code>AX_COMPILER_FLAGS</code> ao <file>configure.ac</file>. Se você está usando cópias de macros autoconf-archive na árvore do projeto, copie <link href="http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_compiler_flags.m4"> <file>ax_compiler_flags.m4</file></link> para o diretório <file>m4/</file> deste. Note que ele depende das macros de autoconf-archive a seguir, as quais são licenciadas sob GPL e, portanto, potencialmente não podem ser copiadas para a árvore. Elas podem permanecer no autoconf-archive, com este como uma dependência de tempo de compilação do projeto:</p>
    <list>
      <item><p><code>ax_append_compile_flags.m4</code></p></item>
      <item><p><code>ax_append_flag.m4</code></p></item>
      <item><p><code>ax_check_compile_flag.m4</code></p></item>
      <item><p><code>ax_require_defined.m4</code></p></item>
    </list>

    <p><code>AX_COMPILER_FLAGS</code> oferece suporte a desabilitar <code>-Werror</code> para compilações de lançamento, de forma que lançamentos sempre seja possível compilar com novos compiladores que podem ter introduzido mais avisos. Defina seu terceiro parâmetro para “yes” para compilações de lançamento (e apenas compilações de lançamento) para habilitar essa funcionalidade. Compilações de desenvolvimento e de integração contínua (em inglês “continuous integration” ou, abreviado, “CI”) deve sempre ter <code>-Werror</code> habilitado.</p>

    <p>Compilações de lançamento podem ser detectadas usando a macro <link href="http://www.gnu.org/software/autoconf-archive/ax_is_release.html"><code>AX_IS_RELEASE</code></link>, podendo o seu resultado ser passado diretamente para <code>AX_COMPILER_FLAGS</code>:</p>
    <code style="valid">AX_IS_RELEASE([git])
AX_COMPILER_FLAGS([WARN_CFLAGS],[WARN_LDFLAGS],[$ax_is_release])</code>

    <p>A escolha de política de estabilidade de lançamento (o primeiro argumento para <code>AX_IS_RELEASE</code>) deve ser feita por projeto, levando em consideração a <link xref="versioning">estabilidade de versionamento</link> do projeto.</p>
  </section>

  <section id="gdb">
    <title>GDB</title>

    <p>GDB é o depurador padrão para C no Linux. Seu uso mais comum é para depurar travamentos, e para analisar o código enquanto ele é executado. Um tutorial completo para usar GDB é fornecido <link href="https://sourceware.org/gdb/current/onlinedocs/gdb/"> aqui</link>.</p>

    <p>Para executar GDB em um programa dentro da árvore fonte, use <cmd>libtool exec gdb --args <var>./nome-do-programa</var> <var>--alguns --argumentos --aqui</var></cmd></p>

    <p>Isso é necessário porque o libtool interfaceia cada binário compilado na árvore fonte em um script shell que define algumas variáveis libtool. Não é necessário para depurar executáveis instalados.</p>

    <p>GDB possui muitos recursos avançados que podem ser combinados para essencialmente criar pequenos scripts de depuração, ativados por diferentes pontos de interrupção no código. Algumas vezes, essa é uma abordagem útil (para <link href="https://tecnocode.co.uk/2010/07/12/reference-count-debugging-with-gdb/">depuração de contagem de referência</link>), mas outras vezes simplesmente usar <link href="https://developer.gnome.org/glib/stable/glib-Message-Logging.html#g-debug"> <code>g_debug()</code></link> para emitir uma mensagem de depuração é mais simples.</p>
  </section>

  <section id="valgrind">
    <title>Valgrind</title>

    <p>Valgrind é uma suíte de ferramentas para instrumentar e perfilar programas. Sua ferramenta mais famosa é o <link xref="#memcheck">memcheck</link>, mas há, no Valgrind, também várias outras ferramentas poderosas e úteis. Elas são cobertas separadamente nas seções a seguir.</p>

    <p>Uma forma útil de executar Valgrind é executar uma suíte de teste de unidade do programa sob Valgrind, configurando-o para retornar um código de status indicando o número de erros que ele encontrou. Quando executado como parte de <cmd>make check</cmd>, isso fará com que as verificações tenham sucesso se Valgrind encontrar nenhum problema; do contrário, falhará. Porém, executar <cmd>make check</cmd> sob Valgrind não é algo trivial de se fazer na linha de comando. Uma macro, <link href="http://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html"> <code>AX_VALGRIND_CHECK</code></link> pode ser usada para adicionar um novo alvo <cmd>make check-valgrind</cmd> para automatizar isso. Para usá-lo:</p>
    <steps>
      <item><p>Copie <link href="http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_valgrind_check.m4"> <file>ax_valgrind_check.m4</file></link> para o diretório <file>m4/</file> de seu projeto.</p></item>
      <item><p>Adicione <code>AX_VALGRIND_CHECK</code> para <file>configure.ac</file>.</p></item>
      <item><p>Adicione <code>@VALGRIND_CHECK_RULES@</code> para o <file>Makefile.am</file> em cada diretório que contém testes de unidade.</p></item>
    </steps>

    <p>Quando <cmd>make check-valgrind</cmd> é executado, ele salva seus resultados em <file>test-suite-*.log</file>, um arquivo de registro por ferramenta. Note que você precisará executá-lo a partir de um diretório contendo os testes de unidade.</p>
    <p>Valgrind possui uma forma de suprimir falsos positivos, usando <link href="http://valgrind.org/docs/manual/manual-core.html#manual-core.suppress">arquivos de supressão</link>. Estes listam padrões que pode corresponder a rastros de pilhas de erros. Se um rastro de pilha de um erro corresponde a parte de uma entrada de supressão, ele não é relatado. Por vários motivos, GLib atualmente causa vários falsos positivos no <link xref="#memcheck">memcheck</link> e <link xref="#helgrind-and-drd">helgrind e drd</link>, o que deve ser suprimido por padrão para Valgrind ser útil. Por este motivo, todo projeto deve usar um arquivo de supressão padrão de GLib, bem como um específico do projeto.</p>

    <p>Há suporte a arquivos de supressão na macro <code>AX_VALGRIND_CHECK</code>:</p>
    <code>@VALGRIND_CHECK_RULES@
VALGRIND_SUPPRESSIONS_FILES = meu-projeto.supp glib.supp
EXTRA_DIST = $(VALGRIND_SUPPRESSIONS_FILES)</code>

    <section id="memcheck">
      <title>memcheck</title>

      <p>O memcheck é um analisador de uso e alocação de memória. Ele detecta problemas com acessos e modificações de memória da heap (alocações e liberações). É uma ferramenta altamente robusta e madura, e sua saída pode ser totalmente confiada. Se ele diz que “definitely” é um vazamento de memória, definitivamente há um vazamento de memória que deve ser corrigido. Se ele diz que “potentially” é um vazamento de memória, pode haver um vazamento a ser corrigido, ou pode ser uma memória alocada em tempo de inicialização e usada ao longo da vida do programa sem precisar ser liberada.</p>

      <p>Para executar memcheck manualmente em um programa instalado, use:</p>
      <p><cmd>valgrind --tool=memcheck --leak-check=full <var>nome-do-meu-programa</var></cmd></p>

      <p>Ou, se está executando seu programa a partir do diretório fonte, use o seguinte para evitar a execução de verificação de vazamento em scripts auxiliares do libtool:</p>
      <p><cmd>libtool exec valgrind --tool=memcheck --leak-check=full <var>./nome-do-meu-programa</var></cmd></p>

      <p>Valgrind lista cada problema de memória que ele detecta, junto com um rastro curto (se você compilou seu programa com símbolos de depuração), permitindo que a causa do erro de memória seja apontada e corrigida.</p>

      <p>Um tutorial completo sobre uso do memcheck está <link href="http://valgrind.org/docs/manual/mc-manual.html">aqui</link>.</p>
    </section>

    <section id="cachegrind-and-kcachegrind">
      <title>cachegrind e KCacheGrind</title>

      <p>cachegrind é um perfilador de desempenho do cache que também pode medir a execução de uma instrução e, portanto, é muito útil para perfilar desempenho em geral de um programa. <link href="http://kcachegrind.sourceforge.net/html/Home.html"> KCacheGrind</link> é uma interface gráfica útil para isso que permite visualização e exploração de dados de perfil, e as ferramentas raramente devem ser usados separadamente.</p>

      <p>cachegrind funciona simulando a hierarquia de memória do processador, de forma que há situações em que <link href="http://valgrind.org/docs/manual/cg-manual.html#cg-manual.annopts.accuracy">não é perfeitamente acurado</link>. Porém, seu resultado é sempre suficientemente representativo para ser muito útil em depurar pontos de desempenho.</p>

      <p>Um tutorial completo sobre uso do cachegrind está <link href="http://valgrind.org/docs/manual/cg-manual.html">aqui</link>.</p>
    </section>

    <section id="helgrind-and-drd">
      <title>helgrind e drd</title>

      <p>helgrind e drd são detectores de erro em threads, verificações de condições de corrida em acessos de memória e abusos do <link href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html">API pthredas do POSIX</link>. Elas são ferramentas similares, mas são implementadas usando técnicas diferentes, de forma que ambas deveriam ser usadas.</p>

      <p>Os tipos de erros detectados pelo helgrind e drd são: dados acessados por múltiplas threads sem travamento consistente, alterações na ordem de aquisição de trava, liberação um mutex enquanto ele está travado, travamento de um mutex travado, destravamento de um mutex destravado e vários outros erros. Cada erro, quando detectado, é emitido para o console em um pequeno relatório, com um relatório separado fornecendo os detalhes de alocação ou criação de mutexes ou threads envolvidos, de forma que suas definições podem ser localizadas.</p>

      <p>helgrind e drd podem produzir mais falsos positivos que memcheck ou cachegrind, de forma que suas saídas podem ser estudadas com um pouco de cuidado. Porém, problemas em threads são notoriamente elusivos mesmo para programadores mais experientes, de forma que erros de helgrind e drd não devem ser desconsiderados.</p>

      <p>Tutorias completos sobre usar helgrind e drd estão <link href="http://valgrind.org/docs/manual/hg-manual.html">aqui</link> e <link href="http://valgrind.org/docs/manual/drd-manual.html">aqui</link>.</p>
    </section>

    <section id="sgcheck">
      <title>sgcheck</title>

      <p>sgcheck é um verificador de limites de vetor que detecta acessos a vetores que podem ter ultrapassados o tamanho do vetor. Porém, é uma ferramenta muito jovem, ainda marcada como experimental e, portanto, pode produzir muitos mais falsos positivos que outras ferramentas.</p>

      <p>Por ser experimental, sgcheck deve ser executado passando <cmd>--tool=exp-sgcheck</cmd> para o Valgrind, em vez de <cmd>--tool=sgcheck</cmd>.</p>

      <p>Um tutorial completo sobre uso do sgcheck está <link href="http://valgrind.org/docs/manual/sg-manual.html">aqui</link>.</p>
    </section>
  </section>

  <section id="gcov-and-lcov">
    <title>gcov e lcov</title>

    <p><link href="https://gcc.gnu.org/onlinedocs/gcc/Gcov.html">gcov</link> é uma ferramenta de perfilamento construída em GCC que instrumenta código adicionando instruções extras em tempo de compilação. Quando o programa é executado, esse código gera os arquivos de saída de perfilamento <file>.gcda</file> e <file>.gcno</file>. Esses arquivos podem ser analisados pela ferramenta <cmd>lcov</cmd>, que gera relatórios visuais de cobertura de código em tempo de execução, linhas destacadas de código no projeto que executa mais do que outros.</p>

    <p>Um uso crítico para essa coleção de dados de cobertura de código é quando se está executando testes de unidade: se a quantidade de código coberto (por exemplo, quais linhas em particular foram executadas) pelos testes de unidade é conhecida, ela pode ser usado para guiar expansões posteriores de testes de unidade. Ao verificar regularmente a cobertura de código atingido pelos testes de unidade e expandindo-os para 100%, você pode se certificar de que todo o projeto está sendo testado. Frequentemente é o caso de que um teste de unidade exercita a maioria do código, mas não um caminho de fluxo de controle em particular, o qual acaba por abrigar erros residuais.</p>

    <p>lcov oferece suporte a <link href="http://en.wikipedia.org/wiki/Code_coverage#Basic_coverage_criteria">medida de cobertura de ramo</link>, de forma que é seja adequado para demonstrar cobertura de código crítico de segurança. É perfeitamente adequado para código crítico que não seja de segurança.</p>

    <p>Como a cobertura de código tem que estar habilitada em ambos tempo de compilação de execução, uma macro é fornecida para simplificar as coisas. A macro <link href="http://www.gnu.org/software/autoconf-archive/ax_code_coverage.html"> <code>AX_CODE_COVERAGE</code></link> adiciona um alvo de <cmd>make check-code-coverage</cmd> ao sistema de compilação, o qual executa os testes de unidade com cobertura de código habilitada e gera um relatório usando <cmd>lcov</cmd>.</p>

    <p>Para adicionar suporte ao <code>AX_CODE_COVERAGE</code> a um projeto:</p>
    <steps>
      <item><p>Copie <link href="http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_code_coverage.m4"> <file>ax_code_coverage.m4</file></link> para o diretório <file>m4/</file> de seu projeto.</p></item>
      <item><p>Adicione <code>AX_CODE_COVERAGE</code> para <file>configure.ac</file>.</p></item>
      <item><p>Adicione <code>@CODE_COVERAGE_RULES</code> ao <file>Makefile.am</file> de topo de nível.</p></item>
      <item><p>Adicione <code>$(CODE_COVERAGE_CFLAGS)</code> às variáveis <code><var>*</var>_CFLAGS</code> do automake para cada alvo ao qual você deseja cobertura, por exemplo para todas bibliotecas com nenhum código de teste de unidade. Faça o mesmo para <code>$(CODE_COVERAGE_LDFLAGS)</code> e <code><var>*</var>_LDFLAGS</code>.</p></item>
    </steps>

    <p>A documentação sobre o uso de gcov e lcov está <link href="http://ltp.sourceforge.net/coverage/lcov.php">aqui</link>.</p>
  </section>

  <section id="sanitizers">
    <title>Sanitizadores de endereço, thread e comportamentos indefinidos</title>

    <p>GCC e Clang oferecem suporte a vários sanitizadores: conjuntos de código extra e verificações que opcionalmente podem ser compilados nele para um aplicativo e usado para sinalizar vários comportamentos incorretos em tempo de execução. Elas são ferramentas poderosas, mas em especial têm que estar habilitadas, recompilando seu aplicativo para habilitá-los e desabilitá-los. Eles não podem estar habilitados ao mesmo tempo que um ao outro, ou usado ao mesmo tempo que <link xref="#valgrind">Valgrind</link>. Eles ainda estão jovens, então possuem pouca integração com outras ferramentarias.</p>

    <p>Todos os sanitizadores estão disponíveis para GCC e Clang, aceitando o mesmo conjunto de opções de compilador.</p>

    <section id="address-sanitizer">
      <title>Sanitizador de endereço</title>

      <p>Também conhecido como “<link href="https://code.google.com/p/address-sanitizer/">address sanitizer</link>” (“asan”), ele detecta erros de uso-após-liberação e estouro de buffer em programas C e C++. Um tutorial completo sobre o uso de asan está <link href="http://clang.llvm.org/docs/AddressSanitizer.html#usage">disponível para Clang</link> — as mesmas instruções devem funcionar para GCC.</p>
    </section>

    <section id="thread-sanitizer">
      <title>Sanitizador de thread</title>

      <p>Também chamado de “<link href="https://code.google.com/p/thread-sanitizer/">thread sanitizer</link>” (“tsan”), ele detecta corridas de dados em localizações de memória, além de uma variedade de usos inválidos de APIs de thread do POSIX. Um tutorial completo sobre o uso de tsan está <link href="http://clang.llvm.org/docs/ThreadSanitizer.html#usage">disponível para Clang</link> — as mesmas instruções devem funcionar para GCC.</p>
    </section>

    <section id="undefined-behavior-sanitizer">
      <title>Sanitizador de comportamento indefinido</title>

      <p>Também chamado de “undefined behavior sanitizer” (“ubsan”), ele é uma coleção de instrumentações menores que detectam vários comportamentos indefinidos em potencial em programas C. Um conjunto de instruções para habilitar ubsan está <link href="http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation">disponível para Clang</link> — as mesmas instruções devem funcionar para o GCC.</p>
    </section>
  </section>

  <section id="coverity">
    <title>Coverity</title>

    <p><link href="http://scan.coverity.com/">Coverity</link> é uma das maiores e mais populares ferramentas comerciais de análise estática disponível. Porém, está disponível para uso para projetos de código aberto e qualquer projeto é encorajado a <link href="https://scan.coverity.com/users/sign_up">se inscrever</link>. A <link href="https://scan.coverity.com/faq#how-get-project-included-in-scan"> análise é realizada</link> executando algumas ferramentas de análise localmente e, então, enviando o código-fonte e resultados como um tarball para o site do Coverity. Os resultados ficam, então, visíveis online para todos os membros do projeto, como anotações do código-fonte do projeto (similarmente a como lconv apresenta seus resultados).</p>

    <p>Como o Coverity não pode ser executado inteiramente localmente, ele não pode ser integrado apropriadamente no sistema de compilação. Porém, scripts existem para varrer automaticamente um projeto e enviar o tarball periodicamente para Coverity. A abordagem recomendada é executar esses scripts periodicamente em um servidor (geralmente como um cronjob), usando um checkout limpo do repositório git do projeto. Coverity automaticamente envia e-mail para membros do projeto sobre novos problemas na análise estática que forem encontrados, de forma que a mesma abordagem que os <link xref="#gcc-and-clang">avisos de compilador</link> possam ser levados: elmitar todos os avisos de análise estática </p>

    <p>Coverity é bom, mas não é perfeito e produz um número de falsos positivos. Esses devem ser marcados como ignorados na interface online.</p>
  </section>

  <section id="clang-static-analyzer">
    <title>Analisador estático do Clang</title>

    <p>Uma ferramenta que pode ser usada para realizar análise estática localmente é o <link href="http://clang-analyzer.llvm.org/">analisador estático do Clang</link>, que é uma ferramenta co-desenvolvida com o <link xref="#gcc-and-clang">compilador Clang</link>. Ele detecta uma variedade de problemas no código C que compiladores não conseguem, e que, do contrário, seria detectável apenas em tempo de execução (usando testes de unidade).</p>

    <p>Clang produz alguns falsos positivos e não há uma forma fácil de ignorá-los. O recomendado é <link href="http://clang-analyzer.llvm.org/faq.html#suppress_issue">preencher um relatório de erro para o analisador estático</link>, de forma que o falso positivo possa ser corrigido no futuro.</p>

    <p>Um tutorial completo sobre o uso Clang está <link href="http://clang-analyzer.llvm.org/scan-build.html">aqui</link>.</p>

    <section id="tartan">
      <title>Tartan</title>

      <p>Porém, apesar de todos os poderes do analisador estático do Clang, ele não pode detectar problemas com bibliotecas específicas, como o GLib. Isso é um problema, se um projeto usa exclusivamente o GLib, e raramente usa APIs do POSIX (o qual Clang entende). Há um plug-in disponível para o analisador estático do Clang, chamado <link href="http://people.collabora.com/~pwith/tartan/">Tartan</link>, que estende o Clang de forma a oferecer suporte a verificações de algumas das APIs comuns do GLib.</p>

      <p>Tartan ainda é um software jovem, então ele produzirá falsos positivos e pode travar quando executado em algum código. Porém, ele pode localizar erros legítimos bem rapidamente, e compensa executar frequentemente sobre um código base para detectar novos erros no uso do GLib no código. Por favor, <link href="http://people.collabora.com/~pwith/tartan/#troubleshooting"> relate quaisquer problemas com Tartan</link>.</p>

      <p>Um tutorial completo sobre habilitar Tartan para uso com o analisador estático do Clang está <link href="http://people.collabora.com/~pwith/tartan/#usage-standalone"> aqui</link>. Se configurado corretamente, a saída do Tartan será misturada com a saída normal do analisador estático.</p>
    </section>
  </section>
</page>