1 概述

Valgrind可以有效地监测处大多数内存问题,你肯定忍不住会想,既然c/c++的内存问题这么常见,为什么不在编译器中加入内存问题检测的功能呢? 很可惜,GCC中还目前还不支持内存检测,可喜的是,clang支持。这里我们看看如何用clang发现内存问题

2 clang

clang 是一个C、C++、Objective-C编程语言的编译器前端。它采用了底层虚拟机作为其后端。它的目标是提供一个GNU编译器套装(GCC)的替代品, 作者是克里斯·拉特纳,在苹果公司的赞助下进行开发。

3 内存泄漏监测

AddressSanitizer是clang中的一个内存错误检测器,它可以检测到以下问题:

  • Out-of-bounds accesses to heap, stack and globals
  • Use-after-free
  • Use-after-return (to some extent)
  • Double-free, invalid free
  • Memory leaks (experimental)

使用clang编译代码时用-fsanitize=address就能打开AddressSanitizer工具,为了在检测到内存错误时打印出您的程序调用栈,需要在编译时加上选项 -fno-omit-frame-pointer选项,同时为了得出更清晰的调用栈信息,请用-O1选项编译程序。

4 示例代码

下面我用clang3.4做一个示例

 1:  int main()
2: {
3: char *p = malloc(sizeof(char) * 10);
4: if (p == NULL) {
5: return 0;
6: }
7:
8: struct elem *e = malloc(sizeof(struct elem));
9: if (e == NULL) {
10: free(p);
11: return 0;
12: }
13:
14: e->a = 10;
15: e->b = 10.10;
16: e->c = p;
17:
18: double *xx = &e->b;
19:
20: printf("%f\n", *xx);
21:
22: free(e);
23:
24: printf("%f\n", *xx);
25:
26: return 0;
27: }

上面的代码中有两处问题,一是p未被释放,导致了内存泄漏;二是xx指向了一块被释放了的内存。我们看看怎么用clang检测这两个问题

4.1 编译它

1:  clang -O1 -g -fsanitize=address -fno-omit-frame-pointer -o core core.c

4.2 用AddressSanitizer监测进程的内存泄漏

直接运行core文件,它就会自动打印出检测到的内存错误

 1:  [cobbliu@kftest25 test]$ ./core
2: 10.100000
3: =================================================================
4: ==11254==ERROR: AddressSanitizer: heap-use-after-free on address 0x60300000efe8 at pc 0x48211a bp 0x7fff2c776450 sp 0x7fff2c776448
5: READ of size 8 at 0x60300000efe8 thread T0
6: #0 0x482119 in main /home/cobbliu/test/core.c:35
7: #1 0x36a101ecdc in __libc_start_main (/lib64/libc.so.6+0x36a101ecdc)
8: #2 0x481f3c in _start (/home/cobbliu/test/core+0x481f3c)
9:
10: 0x60300000efe8 is located 8 bytes inside of 24-byte region [0x60300000efe0,0x60300000eff8)
11: freed by thread T0 here:
12: #0 0x46bca9 in __interceptor_free /home/ads/build23_6u0_x64/workspace/t-coresystem-clang/label/build23_6u0_x64/t-coresystem-clang/llvm-3.4/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:64
13: #1 0x4820c0 in main /home/cobbliu/test/core.c:32
14: #2 0x36a101ecdc in __libc_start_main (/lib64/libc.so.6+0x36a101ecdc)
15:
16: previously allocated by thread T0 here:
17: #0 0x46be29 in malloc /home/ads/build23_6u0_x64/workspace/t-coresystem-clang/label/build23_6u0_x64/t-coresystem-clang/llvm-3.4/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74
18: #1 0x48202a in main /home/cobbliu/test/core.c:18
19: #2 0x36a101ecdc in __libc_start_main (/lib64/libc.so.6+0x36a101ecdc)
20:
21: SUMMARY: AddressSanitizer: heap-use-after-free /home/cobbliu/test/core.c:35 main
22: Shadow bytes around the buggy address:
23: 0x0c067fff9da0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
24: 0x0c067fff9db0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
25: 0x0c067fff9dc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
26: 0x0c067fff9dd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
27: 0x0c067fff9de0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
28: =>0x0c067fff9df0: fa fa fa fa fa fa fa fa fa fa fa fa fd[fd]fd fa
29: 0x0c067fff9e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
30: 0x0c067fff9e10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
31: 0x0c067fff9e20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
32: 0x0c067fff9e30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
33: 0x0c067fff9e40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
34: Shadow byte legend (one shadow byte represents 8 application bytes):
35: Addressable: 00
36: Partially addressable: 01 02 03 04 05 06 07
37: Heap left redzone: fa
38: Heap right redzone: fb
39: Freed heap region: fd
40: Stack left redzone: f1
41: Stack mid redzone: f2
42: Stack right redzone: f3
43: Stack partial redzone: f4
44: Stack after return: f5
45: Stack use after scope: f8
46: Global redzone: f9
47: Global init order: f6
48: Poisoned by user: f7
49: ASan internal: fe
50: ==11254==ABORTING

可以看到,程序在提示core.c的第35行有个heap-use-after-free的错误,而且在最后还有个summary,把出错的代码位置和相应的栈信息打了出来。

5 示例代码2

上面的代码做一些小修改,我们看看它对double-free问题的检测

1:  /...
2: struct elem *e2 = e;
3: free(e);
4: free(e2);
5: /...
6: }

按照上面相同的方法编译并运行后,提示信息如下:

 1:  [cobbliu@kftest25 test]$ ./core
2: 10.100000
3: =================================================================
4: ==11952==ERROR: AddressSanitizer: attempting double-free on 0x60300000efe0 in thread T0:
5: #0 0x46bca9 in __interceptor_free /home/ads/build23_6u0_x64/workspace/t-coresystem-clang/label/build23_6u0_x64/t-coresystem-clang/llvm-3.4/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:64
6: #1 0x4820bd in main /home/cobbliu/test/core.c:34
7: #2 0x36a101ecdc in __libc_start_main (/lib64/libc.so.6+0x36a101ecdc)
8: #3 0x481f3c in _start (/home/cobbliu/test/core+0x481f3c)
9:
10: 0x60300000efe0 is located 0 bytes inside of 24-byte region [0x60300000efe0,0x60300000eff8)
11: freed by thread T0 here:
12: #0 0x46bca9 in __interceptor_free /home/ads/build23_6u0_x64/workspace/t-coresystem-clang/label/build23_6u0_x64/t-coresystem-clang/llvm-3.4/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:64
13: #1 0x4820b0 in main /home/cobbliu/test/core.c:33
14: #2 0x36a101ecdc in __libc_start_main (/lib64/libc.so.6+0x36a101ecdc)
15:
16: previously allocated by thread T0 here:
17: #0 0x46be29 in malloc /home/ads/build23_6u0_x64/workspace/t-coresystem-clang/label/build23_6u0_x64/t-coresystem-clang/llvm-3.4/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74
18: #1 0x482026 in main /home/cobbliu/test/core.c:18
19: #2 0x36a101ecdc in __libc_start_main (/lib64/libc.so.6+0x36a101ecdc)
20:
21: SUMMARY: AddressSanitizer: double-free /home/ads/build23_6u0_x64/workspace/t-coresystem-clang/label/build23_6u0_x64/t-coresystem-clang/llvm-3.4/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:64 __interceptor_free
22: ==11952==ABORTING

可以看到,AddressSanitizer报错,说core.c的34行有一个double-free的错误

6 示例代码3

上面的代码做一些小修改,把释放e的代码注释掉,看看它对内存泄漏的检测

1:  /...
2: //free(e);
3: /...
4: }

按照上面相同的方法编译并运行后,提示信息如下:

1:  [cobbliu@kftest25 test]$ ./core
2: 10.100000

可以看到,对内存泄漏,AddressSanitizer无法检测出来 clang中有一个工具叫LeakSanitizer,它的设计目标是用来检测内存泄漏。直到3.7版,LeakSanitizer也是在实验阶段。

7 AddressSanitizer的缺陷

  • AddressSanitizer工具编译的程序的堆栈和栈占用比原生程序的大。
  • AddressSanitizer不支持静态编译

更新:gcc4.8版本之后,有了对AddressSanitizer的支持!

Date: 2015-04-16T21:24+0800

Author: Cobbliu

Org version 7.9.3f with Emacs version 24

Validate XHTML 1.0

内存问题的排查工具和方法– Clang的AddressSanitizer的更多相关文章

  1. Linux内存使用情况以及内存泄露分析之工具与方法

    <Linux C/C++ Memory Leak Detection Tool> 1. 内存使用情况分析 1.1 系统总内存分析 通过cat /proc/meminfo,可用的物理内存=M ...

  2. Windows系统中内存泄露与检测工具及方法

    1.检测需要使用的工具:windbg工具.检测前,需要先安装windbg工具.安装了该工具后,会在安装目录下有一个umdh工具.假设windbg安装在以下目录下:D:\Program Files\De ...

  3. erlang 故障排查工具

    系统级别perf top, dstat -tam, vtune 都能很好分析beam 瓶颈,本文主要erlang 级别排查: 1. 反编译 确认线上运行代码是否正确,reltools没掌握好,升级偶尔 ...

  4. 内存问题排查工具 --- valgrind

    1. 概述 2. Valgrind 3. 内存泄漏监测 3.1. 示例代码 3.2. 编译它 3.3. 用Valgrind监测进程的内存泄漏 4. 悬挂指针 4.1. 示例代码 4.2. Valgri ...

  5. iOS内存优化及排查方法

    1.IBOutlet 对象需要release 2.不停的往UIView,特别是UIScrollView上add相同SubView.一定要记得清除之前的SubView,并且在dealloc函数中执行该方 ...

  6. 内存泄漏 之 MAT工具的使用

    1 内存泄漏的排查方法 Dalvik Debug Monitor Server (DDMS) 是 ADT插件的一部分,其中有两项功能可用于内存检查 : ·    heap 查看堆的分配情况 ·     ...

  7. 我的java问题排查工具单

    前言 平时的工作中经常碰到很多疑难问题的处理,在解决问题的同时,有一些工具起到了相当大的作用,在此书写下来,一是作为笔记,可以让自己后续忘记了可快速翻阅,二是分享,希望看到此文的同学们可以拿出自己日常 ...

  8. php-fpm内存泄漏问题排查

    生产环境内存泄漏问题排查,以下是排查思路   生产环境上有严重的内存溢出问题(红色框所示,正常值应为是 20M 左右)同时系统有 Core Dump 文件产生排查过程中还发现一个现象,如果关闭 OPc ...

  9. 一次完整的JVM堆外内存泄漏故障排查记录

    前言 记录一次线上JVM堆外内存泄漏问题的排查过程与思路,其中夹带一些JVM内存分配机制以及常用的JVM问题排查指令和工具分享,希望对大家有所帮助. 在整个排查过程中,我也走了不少弯路,但是在文章中我 ...

随机推荐

  1. 服务器主机上RAID Controller的Read Ahead Policy

    RAID控制器(卡)会根据Read Ahead Policy 来决定是否只读取应用程序所请求的一块数据, 还是从硬盘上读取整个stripe. 这个policy会对读的性能产生影响. No Read A ...

  2. Restore IP Addresses leetcode java

    题目: Given a string containing only digits, restore it by returning all possible valid IP address com ...

  3. [置顶] Hadoop2.2.0中HDFS的高可用性实现原理

    在Hadoop2.0.0之前,NameNode(NN)在HDFS集群中存在单点故障(single point of failure),每一个集群中存在一个NameNode,如果NN所在的机器出现了故障 ...

  4. intel 汇编中断解释

    汇编中的10H中断是由BIOS对显示器和屏幕所提供的服务程序.使用int 10h服务程序时,必须先指定ah寄存器为以下显示服务编号之一,以指定需要调用的功用. 显示服务 (Video Service: ...

  5. Github上Stars最多的53个深度学习项目,TensorFlow遥遥领先

    原文:https://github.com/aymericdamien/TopDeepLearning 项目名称 Stars 项目介绍 TensorFlow 29622 使用数据流图计算可扩展机器学习 ...

  6. elasticsearch控制台中文乱码和jvm内存大小调整。 解决办法:

    修改config下面的jvm.options如下 -Xms256m -Xmx256m # ensure UTF-8 encoding by default (e.g. filenames) #-Dfi ...

  7. [Algorithm] Binary tree: Level Order Traversal

    function Node(val) { return { val, left: null, right: null }; } function Tree() { return { root: nul ...

  8. iPhone8发布后那些搞笑Geek段子合辑 #精选搞笑GEEK段子

    这些段子能把人笑出猪叫声哈哈哈哈哈哈哈哈哈哈哈哈嗝 前方高能!请带好安全帽观看段子手们的表演   只能帮你们到这里了 加了半截刘海,怎么像和天猫合作的了? 杜蕾斯的追热点也很及时啊!十年如一日是啥意思 ...

  9. Windows Service 之 Bug 记录

    1.未能将“obj\x86\Debug\**.exe”复制到“bin\Debug\**.exe”.超出了重试计数 10.失败. 解决方案:关闭 VS 程序,到上述下,把 **.exe 删掉,然后重新打 ...

  10. 【树莓派】RPi desktop系统重启或关机挂起几个问题:plymouth-reboot.service、plymouth-poweroff.service、Deconfiguring network interfaces

    在基于intel平台安装的RPi desktop关机或者重启时,会存在挂起的问题,一直卡着不动. 挂起问题有3个: 系统关机时候,停留在:plymouth-poweroff.service 系统重启时 ...