Partilhar via


Referência de depuração, compilação e linguagem do AddressSanitizer

As seções deste artigo descrevem a especificação da linguagem AddressSanitizer, as opções do compilador e as opções do vinculador. Elas também descrevem as opções que controlam a integração do depurador do Visual Studio específica do AddressSanitizer.

Para obter mais informações sobre o runtime do AddressSanitizer, consulte a referência de runtime. Ela inclui informações sobre funções interceptadas e como conectar alocadores personalizados. Para obter mais informações sobre como salvar despejos de memória do AddressSanitizer, consulte a referência de despejo de memória.

Especificação do idioma

__SANITIZE_ADDRESS__

A macro __SANITIZE_ADDRESS__ do pré-processador é definida como 1 quando /fsanitize=address está definido. Essa macro é útil para que usuários avançados especifiquem condicionalmente o código-fonte para a presença do runtime do AddressSanitizer.

#include <cstdio>

int main() {
    #ifdef __SANITIZE_ADDRESS__
        printf("Address sanitizer enabled");
    #else
        printf("Address sanitizer not enabled");
    #endif
    return 1;
}

__declspec(no_sanitize_address)

O especificador __declspec(no_sanitize_address) pode ser usado para desabilitar seletivamente o Sanitizer em funções, variáveis locais ou variáveis globais. Esse __declspec afeta o comportamento do compilador e não o comportamento de runtime.

__declspec(no_sanitize_address)
void test1() {
    int x[100];
    x[100] = 5; // ASan exception not caught
}

void test2() {
    __declspec(no_sanitize_address) int x[100];
    x[100] = 5; // ASan exception not caught
}

__declspec(no_sanitize_address) int g[100];
void test3() {
    g[100] = 5; // ASan exception not caught
}

Compiler

Opção do compilador /fsanitize=address

A opção de compilador /fsanitize=address instrumenta referências de memória no seu código para capturar erros de segurança de memória em runtime. As conexões de instrumentação conectam cargas, armazenam, definem o escopo, alloca, e funções CRT. Ela pode detectar bugs ocultos, como, por exemplo, fora dos limites, usar após liberação, usar após definição do escopo e assim por diante. Para obter uma lista não exaustiva de erros detectados em runtime, consulte Exemplos de erro do AddressSanitizer.

/fsanitize=addressé compatível com todos os níveis de otimização C++ ou C existentes (por exemplo, /Od, , /O1/O2, e /O2 /GL). O código produzido com essa opção funciona com CRTs estáticos e dinâmicos (por exemplo, /MD, /MDd, /MT e /MTd). Essa opção do compilador pode ser usada para criar um .EXE ou .DLL visando x86 ou x64. As informações de depuração são necessárias para a formatação ideal das pilhas de chamadas. Essa opção do compilador não é compatível com a otimização guiada por perfil.

Para obter exemplos de código que demonstram vários tipos de detecção de erros, consulte Exemplos de erro do AddressSanitizer.

Opção do compilador /fsanitize=fuzzer (experimental)

A opção do compilador /fsanitize=fuzzer adiciona LibFuzzer à lista de bibliotecas padrão. Ela também define as seguintes opções de cobertura do Sanitizer:

Recomendamos o uso de /fsanitize=address com /fsanitize=fuzzer.

Essas bibliotecas são adicionadas à lista de bibliotecas padrão quando você especifica /fsanitize=fuzzer:

Opção de runtime Biblioteca LibFuzzer
/MT clang_rt.fuzzer_MT-{arch}
/MD clang_rt.fuzzer_MD-{arch}
/MTd clang_rt.fuzzer_MTd-{arch}
/MDd clang_rt.fuzzer_MDd-{arch}

Bibliotecas LibFuzzer que omitem a função main também estão disponíveis. É sua responsabilidade definir main e chamar LLVMFuzzerInitialize e LLVMFuzzerTestOneInput quando você usa essas bibliotecas. Para usar uma dessas bibliotecas, especifique /NODEFAULTLIB e vincule explicitamente à seguinte biblioteca que corresponde ao seu tempo de execução e arquitetura:

Opção de runtime Biblioteca LibFuzzer no_main
/MT clang_rt.fuzzer_no_main_MT-{arch}
/MD clang_rt.fuzzer_no_main_MD-{arch}
/MTd clang_rt.fuzzer_no_main_MTd-{arch}
/MDd clang_rt.fuzzer_no_main_MDd-{arch}

Se você especificar /NODEFAULTLIB e não especificar uma dessas bibliotecas, receberá um erro de link de símbolo externo não resolvido.

Opção do compilador /fsanitize-address-use-after-return (experimental)

Por padrão, o compilador MSVC (ao contrário de Clang) não gera código para alocar quadros no heap para capturar erros de uso após o retorno. Para capturar esses erros usando o AddressSanitizer, você deve:

  1. Compile usando a opção /fsanitize-address-use-after-return.
  2. Antes de executar seu programa, execute set ASAN_OPTIONS=detect_stack_use_after_return=1 para definir a opção de verificação de runtime.

A /fsanitize-address-use-after-return opção faz com que o compilador gere código para usar um quadro de pilha dupla no heap quando os locais são considerados "endereços obtidos". Este código é muito mais lento do que apenas usar /fsanitize=address sozinho. Para obter mais informações e um exemplo, confira Erro: stack-use-after-return.

O quadro de pilha dupla no heap permanece após o retorno da função que o criou. Considere um exemplo em que o endereço de um local, alocado a um slot no heap, é usado após o retorno. Os bytes de sombra associados ao quadro de heap falso contêm o valor 0xF9. Esse 0xF9 significa um erro stack-use-after-return quando o runtime relata o erro.

Os quadros de pilha são alocados no heap e permanecem após o retorno das funções. O runtime usa a coleta de lixo para liberar de forma assíncrona esses objetos falsos de quadro de chamadas, após um determinado intervalo de tempo. Endereços de moradores são transferidos para quadros persistentes no heap. É como o sistema pode detectar quando qualquer local é usado após o retorno da função de definição. Para obter mais informações, consulte o algoritmo para uso de pilha após o retorno, conforme documentado pelo Google.

Linker

Opção de vinculador /INFERASANLIBS[:NO]

A /fsanitize=address opção do compilador marca objetos para especificar qual biblioteca AddressSanitizer vincular ao executável. As bibliotecas têm nomes que começam com clang_rt.asan*. A opção do vinculador /INFERASANLIBS (por padrão) vincula essas bibliotecas a partir de seus locais padrão automaticamente. Aqui estão as bibliotecas escolhidas e vinculadas automaticamente.

Observação

Na tabela a seguir, {arch} é ou i386 x86_64. Essas bibliotecas usam convenções Clang para nomes de arquitetura. As convenções MSVC são normalmente x86 e x64 em vez de i386 e x86_64. Elas se referem às mesmas arquiteturas.

Opção CRT Biblioteca de tempo de execução AddressSanitizer (.lib) Binário de tempo de execução de endereço (.dll)
/MT ou /MTd clang_rt.asan_dynamic-{arch}, clang_rt.asan_static_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MD ou /MDd clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}

A opção do vinculador /INFERASANLIBS:NO impede que o vinculador vincule um arquivo de biblioteca clang_rt.asan* do local padrão. Adicione o caminho da biblioteca em seus scripts de compilação se usar essa opção. Caso contrário, o vinculador relatará um erro de símbolo externo não resolvido.

Versões anteriores

Antes do Visual Studio 17.7 Versão Prévia 3, os builds vinculados estaticamente (/MT ou /MTd) não usavam uma dependência de DLL. Em vez disso, o tempo de execução do AddressSanitizer foi vinculado estaticamente ao EXE do usuário. Os projetos DLL carregariam as exportações do EXE do usuário para acessar a funcionalidade ASan. Além disso, projetos vinculados dinamicamente (/MD ou /MTd) usavam bibliotecas e DLLs diferentes, dependendo se o projeto estava configurado para depuração ou versão. Para obter mais informações sobre essas alterações e suas motivações, consulte MSVC Address Sanitizer – Uma DLL para todas as configurações de runtime.

Opção de tempo de execução do CRT DLL ou EXE Bibliotecas de runtime do AddressSanitizer
/MT EXE clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch}
/MT DLL clang_rt.asan_dll_thunk-{arch}
/MD Você pode usar o clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch}
/MTd EXE clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch}
/MTd DLL clang_rt.asan_dbg_dll_thunk-{arch}
/MDd Você pode usar o clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch}

integração com o Visual Studio

Opção do compilador /fno-sanitize-address-vcasan-lib

A opção /fsanitize=address é vinculada em bibliotecas extras para uma experiência aprimorada de depuração do Visual Studio quando uma exceção do AddressSanitizer é gerada. Essas bibliotecas são chamadas de VCAsan. As bibliotecas permitem que o Visual Studio exiba erros do AddressSanitizer no código-fonte. Eles também permitem que o executável gere despejos de memória quando um relatório de erro do AddressSanitizer é criado. Para obter mais informações, consulte a biblioteca de funcionalidades estendidas do AddressSanitizer do Visual Studio.

A biblioteca escolhida depende das opções do compilador e é vinculada automaticamente.

Opção de runtime Versão VCAsan
/MT libvcasan.lib
/MD vcasan.lib
/MTd libvcasand.lib
/MDd vcasand.lib

No entanto, se você compilar usando /Zl (Omitir nome da biblioteca padrão), deverá especificar manualmente a biblioteca. Se não fizer isso, você receberá um erro de link de símbolo externo não resolvido. Aqui estão alguns exemplos típicos:

error LNK2001: unresolved external symbol __you_must_link_with_VCAsan_lib
error LNK2001: unresolved external symbol ___you_must_link_with_VCAsan_lib

A depuração aprimorada pode ser desabilitada em tempo de compilação usando a opção /fno-sanitize-address-vcasan-lib.

A variável de ambiente ASAN_VCASAN_DEBUGGING

A opção do compilador /fsanitize=address produz um binário que expõe bugs de segurança de memória em runtime. Quando o binário é iniciado na linha de comando e o runtime relata um erro, ele imprime os detalhes do erro. Em seguida, ele sai do processo. A variável de ambiente ASAN_VCASAN_DEBUGGING pode ser definida para iniciar o IDE do Visual Studio imediatamente quando o runtime relatar um erro. Essa opção do compilador permite exibir o erro, sobreposto ao código-fonte, na linha e coluna precisas que causaram o erro.

Para habilitar esse comportamento, execute o comando set ASAN_VCASAN_DEBUGGING=1 antes de executar seu aplicativo. Você pode desabilitar a experiência de depuração aprimorada executando set ASAN_VCASAN_DEBUGGING=0.

Confira também

Visão geral do AddressSanitizer
Problemas conhecidos do AddressSanitizer
Referência de runtime do AddressSanitizer
Bytes de sombra de AddressSanitizer
Nuvem do AddressSanitizer ou teste distribuído
Integração do depurador do AddressSanitizer
Exemplos de erro do AddressSanitizer