2017-01-09 53 views
1

選項檢測內存泄漏當我使用Address Sanitizer(clang v3.4)檢測內存泄漏時,我發現使用-O(-O0除外)選項總是會導致無泄漏 - 檢測結果。地址Sanitizer無法使用-O

的代碼很簡單:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main() 
{ 
    int* array = (int *)malloc(sizeof(int) * 100); 
    for (int i = 0; i < 100; i++) //Initialize 
    array[i] = 0; 
    return 0; 
} 

當與-O0編譯,

clang -fsanitize=address -g -O0 main.cpp 

它將正確地檢測存儲器,

==2978==WARNING: Trying to symbolize code, but external symbolizer is not initialized! 

================================================================= 
==2978==ERROR: LeakSanitizer: detected memory leaks 

Direct leak of 400 byte(s) in 1 object(s) allocated from: 
    #0 0x4652f9 (/home/mrkikokiko/sdk/MemoryCheck/a.out+0x4652f9) 
    #1 0x47b612 (/home/mrkikokiko/sdk/MemoryCheck/a.out+0x47b612) 
    #2 0x7fce3603af44 (/lib/x86_64-linux-gnu/libc.so.6+0x21f44) 

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

然而,當加入-O,

clang -fsanitize=address -g -O main.cpp 

沒有檢測到!我在官方文件中沒有發現任何關於它的信息。

+0

你的代碼是C代碼,而不是C++代碼。 C++標籤是錯誤的,應該使用C標籤。 –

+0

你沒有使用數組,也許它被優化了嗎? –

+0

@BasileStarynkevitch請參閱'clang -fsanitize = address -g -O main.cpp'這一行 - 表示OP使用C++(clang編譯器根據文件擴展名'.cpp'選擇語言)。 OP的代碼是有效的C++。 –

回答

5

這是因爲your code is completely optimized away。所得到的組件是一樣的東西:

main:         # @main 
    xorl %eax, %eax 
    retq 

如果不能malloc任何電話,沒有內存分配......因此,沒有內存泄漏。


爲了有AddressSanitizer檢測內存泄漏,您可以:

  • Compile with optimizations disabled,如Simon Kraemer在評論中提到。

  • 馬克arrayvolatilepreventing the optimization

    main:         # @main 
         pushq %rax 
         movl $400, %edi    # imm = 0x190 
         callq malloc     # <<<<<< call to malloc 
         movl $9, %ecx 
    .LBB0_1:        # =>This Inner Loop Header: Depth=1 
         movl $0, -36(%rax,%rcx,4) 
         movl $0, -32(%rax,%rcx,4) 
         movl $0, -28(%rax,%rcx,4) 
         movl $0, -24(%rax,%rcx,4) 
         movl $0, -20(%rax,%rcx,4) 
         movl $0, -16(%rax,%rcx,4) 
         movl $0, -12(%rax,%rcx,4) 
         movl $0, -8(%rax,%rcx,4) 
         movl $0, -4(%rax,%rcx,4) 
         movl $0, (%rax,%rcx,4) 
         addq $10, %rcx 
         cmpq $109, %rcx 
         jne  .LBB0_1 
         xorl %eax, %eax 
         popq %rcx 
         retq 
    
+1

或者你只是用'-O0'進行編譯:https://godbolt.org/g/0ul4bk –

+0

@SimonKraemer:我認爲OP知道這一點,因爲他提到用'-O0'編譯時會報告內存泄漏正確。 –

+0

只是想補充完整... –

3

查看生成的代碼。

GCC & Clang實際上知道malloc的語義。因爲我的Linux/Debian系統上<stdlib.h>包含

extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur; 

__attribute_malloc__ & _wur(和__THROW)的宏別處定義。閱讀GCC documentationCommon Function Attributes,並且鏘文檔says

Clang的目的是支持廣泛的GCC擴展。

我強烈懷疑與-O調用malloc通過移除它優化

在我的Linux/x86-64的使用clang -O -S psbshdk.c(鏗鏘3.8)的機器,我確實得到:

.globl main 
    .align 16, 0x90 
    .type main,@function 
main:         # @main 
    .cfi_startproc 
# BB#0: 
    xorl %eax, %eax 
    retq 
.Lfunc_end0: 
    .size main, .Lfunc_end0-main 
    .cfi_endproc 

地址消毒工作所發射的二進制文件(這將不包含任何malloc調用) 。

順便說一句,你可以編譯clang -O -g然後使用valgrind,或編譯clang -O -fsanitize=address -gclang & gcc都能夠優化並提供一些調試信息(這在優化大量時可能是「近似」的)。