2017-10-19 10 views
2

J'essaie d'ajouter ASAN (adresse de Google/Clang sanitize) à notre projet et bloqué à ce problème.clang et clang ++ avec ASAN générer une sortie différente

Par exemple, nous avons ce simple code C++

#include <iostream> 
int main() { 
    std::cout << "Started Program\n"; 
    int* i = new int(); 
    *i = 42; 
    std::cout << "Expected i: " << *i << std::endl; 
} 

Ensuite, je construire avec clang ++

clang++-3.8 -o memory-leak++ memory_leak.cpp -fsanitize=address -fno-omit-frame-pointer -g 

Le programme donne cette sortie

Started Program 
Expected i: 42 

================================================================= 
==14891==ERROR: LeakSanitizer: detected memory leaks 

Direct leak of 4 byte(s) in 1 object(s) allocated from: 
    #0 0x4f2040 in operator new(unsigned long) (memory-leak+++0x4f2040) 
    #1 0x4f4f00 in main memory_leak.cpp:4:11 
    #2 0x7fae13ce6f44 in __libc_start_main /build/eglibc-SvCtMH/eglibc-2.19/csu/libc-start.c:287 

SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s). 

Cool, ça marche et le symboliseur donne aussi des informations significatives.

Maintenant, je construis ce qui résonnerait

clang-3.8 -o memory-leak memory_leak.cpp -std=c++11 -fsanitize=address -fno-omit-frame-pointer -g -lstdc++ 

Et le programme donne cette sortie

Started Program 
Expected i: 42 

================================================================= 
==14922==ERROR: LeakSanitizer: detected memory leaks 

Direct leak of 4 byte(s) in 1 object(s) allocated from: 
    #0 0x4c3bc8 in malloc (memory-leak+0x4c3bc8) 
    #1 0x7f024a8e4dac in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x5edac) 
    #2 0x7f0249998f44 in __libc_start_main /build/eglibc-SvCtMH/eglibc-2.19/csu/libc-start.c:287 

SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s). 

Ok, il détecte la fuite de mémoire, mais la trace de la pile semble étrange et il n'a pas vraiment inclure la ligne memory_leak.cpp: 4: 11.

J'ai passé pas mal de temps à essayer d'affiner ce problème dans notre base de code et finalement, la seule différence, c'est clang vs clang ++.

Pourquoi cela pose-t-il un problème, ne pouvons-nous pas utiliser clang ++? Nous utilisons bazel, qui utilise le compilateur CC au lieu de CXX pour des raisons de blah-balh. Nous ne pouvons pas forcer aveuglément à l'utiliser CXX car nous avons des dépendances CC qui ne peuvent pas être construites par CXX. Donc ...

Une idée comment obtenir la même sortie ASAN lorsqu'il est utilisé avec clang et clang ++? Ou, comment faire de Bazel l'utilisation de clang ++ pour les cibles C++ et de clang pour les cibles C?

+0

Cela peut ne pas aider mais je vois la même sortie que clang ++ lors de l'utilisation de clang 5.0.0. – Rakete1111

+0

Je pourrais reproduire votre problème avec clang3.8. Sur mon système, la différence cruciale était les différentes commandes de l'éditeur de liens - certains éléments asan manquaient s'ils étaient invoqués avec clang. On dirait un bug pour moi. – ead

+0

Je n'ai jamais utilisé bazel, mais vous pourriez probablement définir la ligne de commande de l'éditeur de liens avec les bonnes bibliothèques – ead

Répondre

0

Cela semble être un bug dans Clang, pourriez-vous déposer un rapport de bug dans their tracker? (EDIT: cela a été [résolu comme non-un-bogue] (développeurs Asan https://github.com/google/sanitizers/issues/872) donc probly doit être corrigé par les développeurs de Bazel à la place).

Quelques détails: lorsque vous utilisez clang ordinaire, il décide de ne pas lier C++ partie de l'exécution Asan comme on peut le voir dans Tools.cpp:

if (SanArgs.linkCXXRuntimes()) 
    StaticRuntimes.push_back("asan_cxx"); 

et SanitizerArgs.cpp:

LinkCXXRuntimes = 
    Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX(); 

(note de la D.CCCIsCXX partie, il vérifie clang par rapport à clang++ alors qu'à la place, ils doivent vérifier le type de fichier).

C++ partie du temps d'exécution contient intercepteurs pour operator new donc ce qui expliquerait pourquoi il manque lorsque vous liez avec clang au lieu de clang++. D'un point de vue positif, vous devriez pouvoir contourner ce problème en ajoutant -fsanitize-link-c++-runtime à vos drapeaux. En ce qui concerne la pile borked, Asan déroule par défaut la pile avec un dérouleur à base de pointeur de trame qui a des problèmes à se dérouler avec du code qui n'a pas été construit avec -fno-omit-frame-pointer (comme libstdc++.so dans votre cas). Voir par exemplethis answer pour un autre exemple d'un tel comportement et des solutions de contournement disponibles.

+0

Merci yugr.Bogue créé: https://github.com/google/sanitizers/issues/872 – user1767432