Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Usando sanitizers

O que são sanitizers?

Sanitizers são ferramentas de instrumentação estática que ajudam a encontrar bugs que os depuradores tradicionais geralmente não conseguem capturar. Isso é particularmente útil quando combinado com Testes unitários em integração contínua.

Os sanitizers podem ser usados no Windows, macOS e Linux usando os compiladores Clang (LLVM), GCC ou Visual Studio. Certas plataformas também podem ter seus próprios sanitizers disponíveis. Em situações em que um único sanitizer é fornecido por vários compiladores diferentes, lembre-se de que a saída e o comportamento deles diferem um pouco.

Usando sanitizers no Godot

Os sanitizers exigem a recompilação do binário. Isso significa que você não pode usar os binários oficiais do Godot para executar os sanitizers.

Ao compilar com qualquer um dos sanitizers ativados, o binário resultante terá o sufixo .san adicionado ao seu nome para distingui-lo de um binário sem sanitizers.

Há um impacto no desempenho, pois muitas verificações adicionais em tempo de execução precisam ser executadas. A utilização de memória também aumentará. É possível habilitar certas combinações de múltiplos sanitizers em um único build. No entanto, cuidado com o impacto no desempenho ao usar múltiplos sanitizers ao mesmo tempo, pois o binário resultante pode ficar excessivamente lento.

Certas opções podem ser passadas para os sanitizers sem a necessidade de recompilar o binário, utilizando variáveis de ambiente.

Sanitizador de endereços (ASAN)

O verificador de endereços (address sanitizer) é geralmente o sanitizer mais utilizado. Ele pode diagnosticar problemas como buffer overruns e acessos fora dos limites (out-of-bounds). Se o motor travar com uma mensagem como free(): invalid pointer, isso normalmente é o resultado de um estouro de buffer. (Esta mensagem é impressa pelo runtime do C, não pelo Godot.)

In certas situações (como detectar leituras de memória não inicializada), o address sanitizer não é suficiente. O Sanitizador de memória (MSAN) deve ser usado em seu lugar.

Também é possível detectar situações de uso após o retorno (use-after-return) especificando a variável de ambiente ASAN_OPTIONS=detect_stack_use_after_return=1 antes de executar o Godot (não ao compilá-lo). Isso aumenta a sobrecarga de tempo de execução do address sanitizer, portanto, ative esse recurso apenas quando realmente precisar dele.

Para habilitar o address sanitizer em um build do Godot, passe a opção do SCons use_asan=yes ao compilar. Ativar o ASAN geralmente torna o binário resultante cerca de 2× mais lento.

Aviso

Devido a uma decisão de projeto, os sanitizers de endereço, memória e thread são mutuamente exclusivos. Isso significa que você só pode usar um desses sanitizers em um determinado binário.

Sanitizador de vazamentos (LSAN)

O leak sanitizer pode detectar vazamentos de memória (memory leaks), que são situações em que a memória que não está mais em uso nunca é liberada pelo programa em execução. Isso pode potencialmente levar a situações de falta de memória se o programa rodar por tempo suficiente. Como o Godot pode rodar em servidores dedicados por meses ou até anos sem reiniciar, é importante corrigir os vazamentos de memória quando eles ocorrerem.

Para habilitar o leak sanitizer em um build do Godot, passe a opção do SCons use_lsan=yes ao compilar. Ativar o LSAN tem apenas uma pequena sobrecarga de desempenho, mas o programa será muito mais lento para fechar, pois a detecção de vazamentos ocorre quando o programa é encerrado.

Sanitizador de memória (MSAN)

O memory sanitizer complementa o Sanitizador de endereços (ASAN). Ao contrário do address sanitizer, o memory sanitizer pode detectar leituras de memória não inicializada.

Para habilitar o memory sanitizer em um build do Godot, passe a opção do SCons use_msan=yes ao compilar. Ativar o MSAN geralmente torna o binário resultante cerca de 3× mais lento.

Aviso

Devido a uma decisão de projeto, os sanitizers de endereço, memória e thread são mutuamente exclusivos. Isso significa que você só pode usar um desses sanitizers em um determinado binário.

Sanitizador de threads (TSAN)

O thread sanitizer é usado para rastrear condições de corrida relacionadas ao multithreading. Uma condição de corrida ocorre quando vários threads tentam modificar os mesmos dados ao mesmo tempo. Como o agendamento de threads pode ser ordenado de qualquer maneira pelo sistema operacional, isso leva a um comportamento incorreto que ocorre apenas ocasionalmente (e pode ser difícil de rastrear como resultado). Para evitar uma condição de corrida, você precisa adicionar um bloqueio para garantir que apenas um thread possa acessar os dados compartilhados em um determinado momento.

Para habilitar o thread sanitizer em um build do Godot, passe a opção do SCons use_tsan=yes ao compilar. Ativar o TSAN geralmente torna o binário resultante 10× mais lento, além de multiplicar o uso de memória por um fator de aproximadamente 8×.

Aviso

Devido a uma decisão de projeto, os sanitizers de endereço, memória e thread são mutuamente exclusivos. Isso significa que você só pode usar um desses sanitizers em um determinado binário.

Nota

No Linux, se você se deparar com o seguinte erro:

FATAL: ThreadSanitizer: unexpected memory mapping

Você pode precisar diminuir temporariamente a entropia da Randomização do Layout do Espaço de Endereçamento (ASLR) em seu sistema com:

sudo sysctl vm.mmap_rnd_bits=28

Ou, de preferência, desativá-la completamente com:

sudo sysctl kernel.randomize_va_space=0

E assim que terminar com o thread sanitizer, aumente a entropia da ASLR com:

sudo sysctl vm.mmap_rnd_bits=32

Ou reative a ASLR com:

sudo sysctl kernel.randomize_va_space=2

Reiniciar sua máquina também reverterá o estado da ASLR para seus valores padrão.

É importante reverter as alterações o mais rápido possível, pois diminuir a entropia da ASLR ou desativar a ASLR completamente pode ser um risco de segurança.

Sanitizador de comportamento indefinido (UBSAN)

O undefined behavior sanitizer é usado para rastrear situações em que o programa exibe um comportamento aleatório e imprevisível. Isso se deve a códigos C/C++ que são aceitos pelo compilador, mas não são corretos. Compilar com um conjunto diferente de otimizações também pode alterar os resultados observados de um comportamento indefinido.

Para habilitar o undefined behavior sanitizer em um build do Godot, passe a opção do SCons use_ubsan=yes ao compilar. Ativar o UBSAN apresenta apenas uma pequena sobrecarga de desempenho.

Sanitizers específicos de plataforma

Web

Ao compilar para a Web, há 2 opções adicionais de sanitizer do SCons disponíveis:

  • use_assertions=yes habilita as asserções de tempo de execução do Emscripten, que podem capturar vários problemas.

  • use_safe_heap=yes habilita o sanitizer SAFE_HEAP do Emscripten. Ele fornece funcionalidade semelhante ao ASAN, mas foca em problemas específicos do WebAssembly. O SAFE_HEAP não tem garantia de ser compatível com o ASAN e o UBSAN no mesmo binário, portanto você pode ter que buildá-lo separadamente.