Riferimento di debug, compilazione e linguaggio AddressSanitizer
Le sezioni di questo articolo descrivono le opzioni del linguaggio AddressSanitizer, le opzioni del compilatore e il linker. Descrivono anche le opzioni che controllano l'integrazione del debugger di Visual Studio specifiche per AddressSanitizer.
Per altre informazioni sul runtime AddressSanitizer, vedere le informazioni di riferimento sul runtime. Include informazioni sulle funzioni intercettate e su come associare allocatori personalizzati. Per altre informazioni sul salvataggio di dump di arresto anomalo del sistema da errori AddressSanitizer, vedere le informazioni di riferimento sul dump di arresto anomalo del sistema.
Specifiche del linguaggio
__SANITIZE_ADDRESS__
La __SANITIZE_ADDRESS__
macro del preprocessore viene definita come 1
quando /fsanitize=address
è impostata. Questa macro è utile per gli utenti avanzati di specificare in modo condizionale il codice sorgente per la presenza del runtime 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)
L'identificatore __declspec(no_sanitize_address)
può essere usato per disabilitare in modo selettivo il servizio di purificazione in funzioni, variabili locali o variabili globali. Ciò __declspec
influisce sul comportamento del compilatore, non sul comportamento di 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
}
Compilatore
/fsanitize=address
(opzione del compilatore)
L'opzione /fsanitize=address
del compilatore instrumenta i riferimenti alla memoria nel codice per rilevare gli errori di sicurezza della memoria in fase di esecuzione. Gli hook di strumentazione caricano, archiviano, ambiti, alloca
e funzioni CRT. Può rilevare bug nascosti, ad esempio out-of-bounds, use-after-free, use-after-scope e così via. Per un elenco non completo degli errori rilevati in fase di esecuzione, vedere Esempi di errore AddressSanitizer.
/fsanitize=address
è compatibile con tutti i livelli di ottimizzazione C++ o C esistenti (ad esempio, /Od
, /O1
/O2
, e /O2 /GL
). Il codice prodotto con questa opzione funziona con CRT statici e dinamici (ad esempio, /MD
, /MT
/MDd
, e /MTd
). Questa opzione del compilatore può essere usata per creare un .EXE o .DLL destinato a x86 o x64. Le informazioni di debug sono necessarie per una formattazione ottimale degli stack di chiamate. Questa opzione del compilatore non è supportata con l'ottimizzazione guidata del profilo.
Per esempi di codice che illustra diversi tipi di rilevamento degli errori, vedere Esempi di errore AddressSanitizer.
/fsanitize=fuzzer
opzione del compilatore (sperimentale)
L'opzione /fsanitize=fuzzer
del compilatore aggiunge LibFuzzer all'elenco di librerie predefinito. Imposta anche le seguenti opzioni di copertura per il servizio di purificazione:
- Punti di strumentazione perimetrale (
/fsanitize-coverage=edge
), - contatori inline a 8 bit (
/fsanitize-coverage=inline-8bit-counters
), - confronti (
/fsanitize-coverage=trace-cmp
), e - divisioni integer (
/fsanitize-coverage=trace-div
).
È consigliabile usare /fsanitize=address
con /fsanitize=fuzzer
.
Queste librerie vengono aggiunte all'elenco di librerie predefinito quando si specifica /fsanitize=fuzzer
:
Opzione di runtime | Libreria 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} |
Sono disponibili anche librerie LibFuzzer che omettono la main
funzione. È responsabilità dell'utente definire main
e chiamare LLVMFuzzerInitialize
e LLVMFuzzerTestOneInput
quando si usano queste librerie. Per usare una di queste librerie, specificare /NODEFAULTLIB
e collegare in modo esplicito la libreria seguente che corrisponde al runtime e all'architettura:
Opzione di runtime | Libreria di no_main LibFuzzer |
---|---|
/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 si specifica e non si specifica /NODEFAULTLIB
una di queste librerie, verrà visualizzato un errore di collegamento al simbolo esterno non risolto.
/fsanitize-address-use-after-return
opzione del compilatore (sperimentale)
Per impostazione predefinita, il compilatore MSVC (a differenza di Clang) non genera codice per allocare frame nell'heap per intercettare gli errori use-after-return. Per rilevare questi errori usando AddressSanitizer, è necessario:
- Compilare usando l'opzione
/fsanitize-address-use-after-return
. - Prima di eseguire il programma, eseguire
set ASAN_OPTIONS=detect_stack_use_after_return=1
per impostare l'opzione di controllo di runtime.
L'opzione /fsanitize-address-use-after-return
fa in modo che il compilatore generi codice per l'uso di un doppio stack frame nell'heap quando le variabili locali vengono considerate "address taken". Questo codice è molto più lento rispetto all'uso /fsanitize=address
solo. Per altre informazioni e un esempio, vedere Errore: stack-use-after-return
.
Il doppio stack frame nell'heap rimane dopo il ritorno dalla funzione che l'ha creata. Si consideri un esempio in cui l'indirizzo di un oggetto locale, allocato a uno slot nell'heap, viene usato dopo la restituzione. I byte di ombreggiatura associati al frame dell'heap falso contengono il valore 0xF9. Questo 0xF9 indica un errore stack-use-after-return quando il runtime segnala l'errore.
Gli stack frame vengono allocati nell'heap e rimangono dopo la restituzione delle funzioni. Il runtime usa Garbage Collection per liberare in modo asincrono questi oggetti frame di chiamata falsi, dopo un determinato intervallo di tempo. Gli indirizzi delle variabili locali vengono trasferiti a frame permanenti nell'heap. È così che il sistema può rilevare quando le variabili locali vengono usate dopo la restituzione della funzione di definizione. Per altre informazioni, vedere l'algoritmo per l'uso dello stack dopo la restituzione , come documentato da Google.
Linker
/INFERASANLIBS[:NO]
opzione del linker
L'opzione /fsanitize=address
del compilatore contrassegna gli oggetti per specificare la libreria AddressSanitizer da collegare al file eseguibile. Le librerie hanno nomi che iniziano con clang_rt.asan*
. L'opzione /INFERASANLIBS
del linker (attivata per impostazione predefinita) collega automaticamente queste librerie dalle posizioni predefinite. Ecco le librerie scelte e collegate automaticamente.
Nota
Nella tabella seguente è {arch}
i386
o x86_64
.
Queste librerie usano convenzioni Clang per i nomi di architettura. Le convenzioni MSVC sono in genere x86
e x64
non i386
e x86_64
. Fanno riferimento alle stesse architetture.
Opzione CRT | Libreria di runtime AddressSanitizer (.lib) | File binario di runtime degli indirizzi (.dll) |
---|---|---|
/MT oppure /MTd |
clang_rt.asan_dynamic-{arch} , clang_rt.asan_static_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
/MD oppure /MDd |
clang_rt.asan_dynamic-{arch} , clang_rt.asan_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
L'opzione /INFERASANLIBS:NO
del linker impedisce al linker di collegare un clang_rt.asan*
file di libreria dal percorso predefinito. Aggiungere il percorso della libreria negli script di compilazione se si usa questa opzione. In caso contrario, il linker segnala un errore di simbolo esterno non risolto.
Versioni precedenti
Nelle versioni precedenti a Visual Studio 17.7 Preview 3, le compilazioni collegate staticamente (/MT
o /MTd
) non usano una dipendenza DLL. Al contrario, il runtime AddressSanitizer è stato collegato staticamente al file EXE dell'utente. I progetti DLL caricano quindi le esportazioni dal file EXE dell'utente per accedere alla funzionalità ASan. Inoltre, i progetti collegati dinamicamente (/MD
o /MTd
) usavano librerie e DLL diverse a seconda che il progetto sia stato configurato per il debug o il rilascio. Per altre informazioni su queste modifiche e sulle relative motivazioni, vedere MSVC Address Sanitizer – One DLL for all Runtime Configurations (Sanificatori indirizzi MSVC - Una DLL per tutte le configurazioni di runtime).
Opzione di runtime CRT | DLL o EXE | Librerie di runtime AddressSanitizer |
---|---|---|
/MT |
EXE | clang_rt.asan-{arch} , clang_rt.asan_cxx-{arch} |
/MT |
DLL | clang_rt.asan_dll_thunk-{arch} |
/MD |
Prima o dopo | 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 |
Prima o dopo | clang_rt.asan_dbg_dynamic-{arch} , clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} |
Integrazione con Visual Studio
/fno-sanitize-address-vcasan-lib
(opzione del compilatore)
L'opzione /fsanitize=address
collega in librerie aggiuntive per un'esperienza di debug migliorata di Visual Studio quando viene generata un'eccezione AddressSanitizer. Queste librerie sono denominate VCAsan. Le librerie consentono a Visual Studio di visualizzare gli errori AddressSanitizer nel codice sorgente. Consentono inoltre al file eseguibile di generare dump di arresto anomalo quando viene creato un report degli errori AddressSanitizer. Per altre informazioni, vedere Libreria delle funzionalità estese di Visual Studio AddressSanitizer.
La libreria scelta dipende dalle opzioni del compilatore e viene collegata automaticamente.
Opzione di runtime | Versione vcasan |
---|---|
/MT |
libvcasan.lib |
/MD |
vcasan.lib |
/MTd |
libvcasand.lib |
/MDd |
vcasand.lib |
Tuttavia, se si esegue la compilazione usando /Zl
(omettere il nome predefinito della libreria), è necessario specificare manualmente la libreria. In caso contrario, verrà visualizzato un errore di collegamento al simbolo esterno non risolto. Di seguito sono riportati alcuni esempi tipici:
error LNK2001: unresolved external symbol __you_must_link_with_VCAsan_lib
error LNK2001: unresolved external symbol ___you_must_link_with_VCAsan_lib
Il debug migliorato può essere disabilitato in fase di compilazione usando l'opzione /fno-sanitize-address-vcasan-lib
.
La variabile di ambiente ASAN_VCASAN_DEBUGGING
L'opzione /fsanitize=address
del compilatore genera un file binario che espone bug di sicurezza della memoria in fase di esecuzione. Quando il file binario viene avviato dalla riga di comando e il runtime segnala un errore, stampa i dettagli dell'errore. Esce quindi dal processo. La ASAN_VCASAN_DEBUGGING
variabile di ambiente può essere impostata per avviare l'IDE di Visual Studio immediatamente quando il runtime segnala un errore. Questa opzione del compilatore consente di visualizzare l'errore, sovrapposto al codice sorgente, alla riga e alla colonna precise che hanno causato l'errore.
Per abilitare questo comportamento, eseguire il comando set ASAN_VCASAN_DEBUGGING=1
prima di eseguire l'applicazione. È possibile disabilitare l'esperienza di debug avanzata eseguendo set ASAN_VCASAN_DEBUGGING=0
.
Vedi anche
Panoramica di AddressSanitizer
Problemi noti di AddressSanitizer
Informazioni di riferimento sul runtime AddressSanitizer
Byte ombreggiatura AddressSanitizer
AddressSanitizer cloud o test distribuiti
Integrazione del debugger AddressSanitizer
Esempi di errore addressSanitizer