2014-03-27 31 views
15

對不起,如果這是一個超級簡單的概念,但我很難獲得正確的心態,以便正確使用clang提供的消毒劑。我應該如何在叮噹中使用消毒劑?

float foo(float f) { return (f/0); } 

我編這個小片段與

clang++ -fsanitize=float-divide-by-zero -std=c++11 -stdlib=libc++ -c source.cpp -o osan 

,我也編譯我的對象的「正常」的版本,不使用消毒

clang++ -std=c++11 -stdlib=libc++ -c source.cpp -o onorm 

我期待一些詳細的輸出,或從控制檯的一些錯誤,但在檢查文件與nm我只發現1差異

nm o* --demangle 

onorm: 
0000000000000000 T foo(float) 

osan: 
       U __ubsan_handle_divrem_overflow 
0000000000000000 T foo(float) 

因此,在消毒版本中有一個未定義的符號,其名稱類似於編譯時使用的消毒劑;但是一切都非常「沉默」,從鏗鏘聲前端沒有任何輸出。

我應該如何使用清潔劑,什麼是正確的工作流程?那個未定義的符號有什麼意義?

+0

您應該將您的程序鏈接到可執行文件並運行它。消毒劑是運行時間的工具。 – osgx

+0

@osgx有趣的是,在我發現沒有人編譯過的文檔中,運行帶有'main'函數的東西......所以我開始意識到這是編譯時工具。 – user2485710

+0

user2485710,哪些文檔?鏗鏘的手冊說:http://clang.llvm.org/docs/UsersManual.html「控制代碼生成... -fsanitize = ...打開**運行時檢查**各種形式的未定義或可疑的行爲...如果檢查失敗,在運行時會產生一個診斷消息來解釋問題。「 – osgx

回答

10

未定義的符號是一個實現清潔劑檢查的功能。如果你看一下生成的代碼:

沒有消毒:

_Z3foof:        # @_Z3foof 
    .cfi_startproc 
# BB#0: 
    xorps %xmm1, %xmm1 
    divss %xmm1, %xmm0 
    ret 

帶消毒:

_Z3foof:        # @_Z3foof 
    .cfi_startproc 
    .long 1413876459    # 0x54460aeb 
    .quad _ZTIFffE 
# BB#0: 
    pushq %rax 
.Ltmp1: 
    .cfi_def_cfa_offset 16 
    movss %xmm0, 4(%rsp)   # 4-byte Spill 
    movd %xmm0, %esi 
    movl $__unnamed_1, %edi 
    xorl %edx, %edx 
    callq __ubsan_handle_divrem_overflow 
    xorps %xmm1, %xmm1 
    movss 4(%rsp), %xmm0   # 4-byte Reload 
    divss %xmm1, %xmm0 
    popq %rax 
    ret 

你看它添加的代碼做使用該功能的檢查。

編譯器應在適當的消毒庫自動鏈接,然後我下面的完整的程序:

float foo(float f) { return (f/0); } 
int main() { 
    foo(1.0f); 
} 

可生產執行時的輸出如下:我建

main.cpp:1:32: runtime error: division by zero 

,並使用跑指令clang++ -fsanitize=undefined main.cpp && ./a.out


如果您希望編譯時檢查您希望啓用更多編譯器警告或靜態分析器。但是,似乎沒有任何警告或靜態分析檢查浮點除零錯誤。

下面是產生一個分析報告的程序:

#include <malloc.h> 

int main() { 
    int *i = (int*) malloc(sizeof(int)); 
} 

clang++ -std=c++11 main.cpp編譯它不產生任何診斷,但clang++ -std=c++11 --analyze main.cpp編譯它報告如下:

main.cpp:4:10: warning: Value stored to 'i' during its initialization is never read 
    int *i = (int*) malloc(sizeof(int)); 
     ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~ 
main.cpp:5:1: warning: Potential leak of memory pointed to by 'i' 
} 
^ 

死者店也可以用-Weverything [-Wunused-value]檢測到,但泄漏只能由分析儀檢測到。

默認全分析結果寫入plist文件。你也可以用下面的命令運行分析:

clang++ --analyze -Xanalyzer -analyzer-output=text main.cpp 
clang++ --analyze -Xanalyzer -analyzer-output=html -o html-dir main.cpp 

要獲得的檢測問題進行了詳細穿行在標準輸出或通過分別的註釋的源代碼的HTML顯示,而不是在plist中。

分析儀檢查列表here

請注意,要使分析儀最好地工作,需要分析整個程序,這意味着它需要連接到構建系統。通常的界面是通過IDE(Xcode)或者帶有make的scan-build工具。 CMake有一些鏗鏘聲的功能,比如產生叮聲號JSON compilation database files,但如果CMake內置了對鐺分析器的內置支持,我不確定。

+0

你用什麼編譯器選項來編譯這個? – user2485710

+1

@ user2485710'clang ++ -fsanitize = undefined main.cpp &&。/ a.out' – bames53

+0

並且您沒有獲得動態鏈接庫?這適用於我,但它看起來像這個靜態鏈接的llvm庫。 – user2485710

6

所以,如果我們在該Controlling Code Generation看文檔,它說(重點煤礦):

Turn on runtime checks for various forms of undefined or suspicious behavior.

This option controls whether Clang adds runtime checks for various forms of undefined or suspicious behavior, and is disabled by default. If a check fails, a diagnostic message is produced at runtime explaining the problem.

所以這些都是運行時檢查不編譯時檢查。所以,如果你在你的代碼中使用foo那麼你會看到下面的輸出:

runtime error: division by zero

請參閱使用-fsanitize=undefined這個例子live

float foo(float f) { return (f/0); } 

int main() 
{ 
    int x = 1 << 100 ; 
    foo(2.0f) ; 
} 

它生成兩個運行時提示:

main.cpp:6:19: runtime error: shift exponent 100 is too large for 32-bit type 'int'

main.cpp:2:36: runtime error: division by zero

更新

關於靜態檢查器,在我對A C++ implementation that detects undefined behavior?的回答中,我提到了幾個工具:STACK,kcc,當然還有Frama-C

顯然clang允許您使用--analyze to run it's static checker,但它似乎最終可能會被禁用,正確的方式來運行它將通過scan-build

同樣在我的自我回答問題Why do constant expressions have an exclusion for undefined behavior?我演示瞭如何在編譯時使用constexprs來捕獲未定義的行爲。

+1

啊,是的。如果他期待編譯時間檢查,那麼消毒劑是錯誤的工具。靜態分析器執行更多的編譯時檢查。 – bames53

+0

現在我理解了這一點,但我仍然認爲它可能對更詳細的輸出更有用。什麼是llvm/clang的靜態分析參考? – user2485710

+0

@ user2485710我對[檢測未定義行爲的C++實現?](http://stackoverflow.com/a/21388572/1708801)的答案對靜態檢查器有一些很好的參考。 –