Última atualização:2026-10-12
AddressSanitizer: Detecção de Memória¶
C e C++ são linguagens muito inseguras e propensas a erros. O Address Sanitizer é uma ferramenta desenvolvida pelo Google para detectar erros de acesso à memória, como use-after-free e vazamentos de memória. Está integrado ao GCC em versões >= 4.8 e pode ser usado em código C e C++. O Address Sanitizer usa instrumentação em tempo de execução para rastrear alocações de memória, o que significa que você deve compilar seu código com o AddressSanitizer para aproveitar plenamente seus recursos.
- Use after free (dangling pointer dereference)
- Heap buffer overflow
- Stack buffer overflow
- Global buffer overflow
- Use after return
- Use after scope
- Initialization order bugs
- Memory leaks
Este artigo apresentará a ferramenta de detecção de memória AddressSanitizer com base nesses 8 cenários.
1.Use after free¶
Tome o código abaixo como exemplo. Primeiro, a palavra-chave new aloca espaço de memória para um inteiro e atribui seu endereço ao ponteiro ptr. Em seguida, a palavra-chave delete libera essa memória. Porém, após a liberação, o programa ainda tenta acessar a memória já liberada através do ponteiro ptr e atribui o valor 10 a essa posição — esse é o erro de uso após liberação.
#include <iostream>
int main() {
int* ptr = new int;
delete ptr;
*ptr = 10; // Use after free
return 0;
}
Ao compilar, adicione a opção abaixo.
Execute o binário gerado e obtenha o resultado a seguir.

2.heap buffer overflow¶
Primeiro, a palavra-chave new aloca no heap um array com dois inteiros e atribui o endereço inicial do array ao ponteiro arr. Em seguida, o programa tenta armazenar o valor 10 na terceira posição do array (índice 2), o que ultrapassa o intervalo válido do array, causando um estouro de buffer no heap.
#include <iostream>
int main() {
int* arr = new int[2];
arr[2] = 10; // Heap buffer overflow
delete[] arr;
return 0;
}
Uso igual ao anterior:
Depois:
Obtemos o resultado de detecção abaixo.

3.stack buffer overflow¶
Na função vulnerableFunction, é definido um array de caracteres buffer com 8 caracteres. Em seguida, usa-se std::cin para ler dados da entrada padrão para buffer, sem limitar o tamanho da entrada. Se o número de caracteres exceder o tamanho de buffer, ocorre um estouro de buffer na pilha.
void vulnerableFunction() {
char buffer[8];
std::cin >> buffer; // Stack buffer overflow
std::cout << "You entered: " << buffer << std::endl;
}
Uso igual ao anterior.

4.global buffer overflow¶
O buffer global (o array buffer) é definido no escopo global do programa, sem limitação suficiente do tamanho da entrada. Se o número de caracteres exceder o tamanho do buffer, ocorre um estouro de buffer global. Semelhante ao estouro na pilha, o estouro de buffer global pode causar instabilidade e problemas de segurança.
#include <iostream>
char buffer[8];
int main() {
std::cin >> buffer; // 全局缓冲区溢出错误
std::cout << "You entered: " << buffer << std::endl;
return 0;
}
Uso igual ao anterior; obtemos:

5.use after return¶
Na função f, o endereço da variável local i é retornado, mas em main tenta-se acessar a variável local já destruída através do ponteiro retornado. Nesse cenário, é possível detectar no binário configurando ASAN_OPTIONS=detect_stack_use_after_return=1.
g++-13 stack_use_after_return.cc -Wall -g -fsanitize=address
ASAN_OPTIONS=detect_stack_use_after_return=1 ./a.out
Código:
Obteremos:

6.use after scope¶
O endereço da variável local x é atribuído ao ponteiro p; porém, após sair do escopo interno, tenta-se acessar a variável local x já fora de escopo através do ponteiro p, causando um erro de uso fora de escopo. Isso também é comportamento indefinido.
Compilação e execução:
g++-13 stack_use_after_scope.cc -Wall -g -fsanitize=address
ASAN_OPTIONS=detect_stack_use_after_scope=0 ./a.out
Em testes, o clang++ detecta; o g++ não consegue detectar.

7.Initialization order bugs¶
Em dois arquivos-fonte diferentes há inicialização da variável global a, mas a ordem de inicialização é incerta. No arquivo init_order_b.cc, tenta-se usar o valor da variável a; devido à ordem de inicialização inconsistente, pode ocorrer comportamento indefinido.
O código é o seguinte:
// init_order_a.cc
int duplicate(int n) { return n * 2; }
auto a = duplicate(2);
// init_order_b.cc
#include <iostream>
extern int a;
auto b = a;
int main() {
std::cout << b << std::endl;
return 0;
}
Quando escrevemos código assim, o resultado é indeterminado: pode ser 4 ou 0, dependendo da ordem de inicialização.
Por exemplo:
Assim a saída é 4; compilando primeiro b e depois a, obtém-se 0.
Quando esse tipo de problema ocorre, podemos usar o AddressSanitizer para detectar a ordem de inicialização.

8.memory leak¶
A palavra-chave new aloca dinamicamente memória para um inteiro, mas antes do término do programa a palavra-chave delete não é usada para liberá-la, causando vazamento de memória.
#include <iostream>
int main() {
int* ptr = new int;
// Missing delete ptr; // Memory leak
return 0;
}
Configure ASAN_OPTIONS=detect_leaks=1.
