内存问题的排查工具和方法– Clang的AddressSanitizer
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的支持!
内存问题的排查工具和方法– Clang的AddressSanitizer的更多相关文章
- Linux内存使用情况以及内存泄露分析之工具与方法
<Linux C/C++ Memory Leak Detection Tool> 1. 内存使用情况分析 1.1 系统总内存分析 通过cat /proc/meminfo,可用的物理内存=M ...
- Windows系统中内存泄露与检测工具及方法
1.检测需要使用的工具:windbg工具.检测前,需要先安装windbg工具.安装了该工具后,会在安装目录下有一个umdh工具.假设windbg安装在以下目录下:D:\Program Files\De ...
- erlang 故障排查工具
系统级别perf top, dstat -tam, vtune 都能很好分析beam 瓶颈,本文主要erlang 级别排查: 1. 反编译 确认线上运行代码是否正确,reltools没掌握好,升级偶尔 ...
- 内存问题排查工具 --- valgrind
1. 概述 2. Valgrind 3. 内存泄漏监测 3.1. 示例代码 3.2. 编译它 3.3. 用Valgrind监测进程的内存泄漏 4. 悬挂指针 4.1. 示例代码 4.2. Valgri ...
- iOS内存优化及排查方法
1.IBOutlet 对象需要release 2.不停的往UIView,特别是UIScrollView上add相同SubView.一定要记得清除之前的SubView,并且在dealloc函数中执行该方 ...
- 内存泄漏 之 MAT工具的使用
1 内存泄漏的排查方法 Dalvik Debug Monitor Server (DDMS) 是 ADT插件的一部分,其中有两项功能可用于内存检查 : · heap 查看堆的分配情况 · ...
- 我的java问题排查工具单
前言 平时的工作中经常碰到很多疑难问题的处理,在解决问题的同时,有一些工具起到了相当大的作用,在此书写下来,一是作为笔记,可以让自己后续忘记了可快速翻阅,二是分享,希望看到此文的同学们可以拿出自己日常 ...
- php-fpm内存泄漏问题排查
生产环境内存泄漏问题排查,以下是排查思路 生产环境上有严重的内存溢出问题(红色框所示,正常值应为是 20M 左右)同时系统有 Core Dump 文件产生排查过程中还发现一个现象,如果关闭 OPc ...
- 一次完整的JVM堆外内存泄漏故障排查记录
前言 记录一次线上JVM堆外内存泄漏问题的排查过程与思路,其中夹带一些JVM内存分配机制以及常用的JVM问题排查指令和工具分享,希望对大家有所帮助. 在整个排查过程中,我也走了不少弯路,但是在文章中我 ...
随机推荐
- C#微信接口之推送模板消息功能示例
本文实例讲述了C#微信接口之推送模板消息功能.分享给大家供大家参考,具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2 ...
- windows下mysql忘记root密码的解决办法
今天早上 一朋友说自己的mysql 忘记root密码了 让我帮忙给看看,因为没有接触过mysql 所以从网上找了一下信息经我亲身实践 已经成功!mysql版本是5.1以下是从网上找的信息: 1. 首 ...
- window.location属性用法及解决一个window.location.search为什么为空的问题
通常用window.location该属性获取页面 URL 地址: 1.什么是window.location? 比如URL:http://b.a.com:88/index.php?name=kang& ...
- UML图中聚合、组合、关联、依赖、泛化的强弱关系
一.泛化 1.说明 泛化是一种继承关系,如果一个类A的所有属性和操作能被另一个类B所继承,则类B不仅可以包含自己独有的属性,而且可以包含类A的属性和操作.继承是类与类或者类与接口之间最常见的关系. 2 ...
- Centos curl ssl 替换 NSS 为 OpenSSL
参考:https://www.latoooo.com/xia_zhe_teng/368.htm 我的系统版本是 Centos 7 64位.为了方便,先安装常用的开发环境. yum groupinsta ...
- 推文《阿里凑单算法首次公开!基于Graph Embedding的打包购商品挖掘系统解析》笔记
推文<阿里凑单算法首次公开!基于Graph Embedding的打包购商品挖掘系统解析>笔记 从17年5月份开始接触Graph Embedding,学术论文读了很多,但是一直不清楚这技术是 ...
- sqrt函数的实现
原文:http://blog.csdn.net/legend050709/article/details/39394381 sqrt算法实现: (一)int sqrt1(int n);求取整数x的平方 ...
- 让人郁闷的.net
一个旧项目,.net 2.0的,因为一个小改动,mongo数据库加了密码,结果折腾两天却无法解决,让人郁闷的地方太多: .net版本多,用的原来的驱动是1.7的,在.net 2.0就可以,mongo服 ...
- Angular入门笔记
AngularJS(下面简称其为ng)是Google开源的一款JavaScript MVC框架,弥补了HTML在构建应用方面的不足,其通过使用指令(directives)结构来扩展HTML词汇,使开发 ...
- VS2017专业版使用最新版Qt5.9.2教程
VS2017专业版使用最新版Qt5.9.2教程(最新教材) 最近三天一直在安装Qt5.9.2,为了能够在自己专业版的VS2017上面使用?可以算是花费了不少的功夫.但是一路上并不是很顺利,就在刚才,终 ...