Back to Top

使用Clang/GCC的Sanitizer提升程序质量

在Clang的Controlling Code Generation 或 GCC的Program Instrumentation Options中提供了一系列的参数,可以帮程序解决一些常见的内存问题。

本文使用Clang。

AddressSanitizer

内存错误是C/C++的最常见的问题,可能导致程序诡异崩溃,十分难查。内存错误检查AddressSanitizer可用来查找如内存溢出,内存重叠等问题,会带来2倍的速度消耗。

开启方法:

  • XCode Edit Scheme->Run->Diagnostics->勾选Address Sanitizer
  • clang -fsanitize=address test.c

示例:

  • AddressSanitizer: stack-buffer-overflow
long long n = 0;
if (*(long long*)&n == *(long long*)"hr");
  • AddressSanitizer: heap-buffer-overflow
    char *ptr = (char *)malloc(5);
if (ptr[-1] == '\0');
if (ptr[12] == '\0');
  • AddressSanitizer: heap-use-after-free
class Test
{
public:
int Release()
{
if (--m_nRef == 0)
delete this;
return m_nRef;
}
int m_nRef = 1;
};

auto p = new Test;
p->Release();
  • AddressSanitizer: strncpy-param-overlap: memory ranges
char sz[64];
sz[0] = '\0';
strncpy(sz, sz, sizeof(sz));
  • AddressSanitizer: memory leak(仅支持linux)
$ cat memory-leak.c
#include <stdlib.h>
void *p;
int main() {
p = malloc(7);
p = 0; // The memory is leaked here.
return 0;
}
% clang -fsanitize=address -g memory-leak.c ; ASAN_OPTIONS=detect_leaks=1 ./a.out
==23646==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 7 byte(s) in 1 object(s) allocated from:
#0 0x4af01b in __interceptor_malloc /projects/compiler-rt/lib/asan/asan_malloc_linux.cc:52:3
#1 0x4da26a in main memory-leak.c:4:7
#2 0x7f076fd9cec4 in __libc_start_main libc-start.c:287
SUMMARY: AddressSanitizer: 7 byte(s) leaked in 1 allocation(s).

UndefinedBehaviorSanitizer

对一些未定义行为的检查,如有符号整数溢出。可使用 UndefinedBehaviorSanitizer来检查。

int num = 100;
for (int i = 0 ; i < 10; ++i)
{
num *= num; // num在第三次循环的时候,产生上溢。
printf("%d\n", num);
}

开启方法:

  • XCodeOther Warning Flags(其他也可)添加: -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error
  • clang -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error undefined.c

未完待续