内存、性能问题分析的利器——valgraind
valgrind是一个知名的分析软件集。我们可以使用它进行内存、多线程及性能等各种问题的分析。它采用非侵入方式,所谓非侵入方式是指:我们不用在代码中插入分析工具的库。这对于开发者来说是友好的。因为如果要将工具编译到文件中,或者要调用其提供的一些API,才能进行问题分析,无疑增大了用户的学习和使用成本。(转载请指明出于breaksoftware的csdn博客)
valgrind [valgrind-options] your-prog [your-prog-options]
当我们需要分析一款软件时,只要采用上面格式的调用。其中your-prog是被分析的程序文件路径,your-prog-options是原本要传递给待分析程序的参数。valgrind-options是valgrind的一些参数,最常用的是--tool=【tool_name】。我们可以使用不同的tool进行不同的分析,比如使用memcheck进行内存问题分析。
valgrind --tool=memcheck ls -l
那么valgrind和memcheck到底是什么关系呢?我们可以通过下图表达出
当待分析程序片段第一次被执行时,valgrind会将代码片段交给工具——比如内存调试时使用的memcheck处理,工具会在代码中插入一些辅助分析的代码片段。新的代码会在valgrind模拟出的CPU上执行。然后valgrind会结合之前读取到的待执行程序和其所关联的库文件的调试信息,输出分析结果。
因为有新插入的代码逻辑,valgrind运行下的程序都比其独立运行时要慢。视选择的工具不同,其效率可能是正常值的1/4~1/50。所以使用valgrind做性能分析时,一般不使用绝对数据,而使用相同环境下的相对数据进行对比。
为了让valgrind读取出准确的调试信息,待分析程序最好使用-O0禁止编译器优化,以及使用-g让编译器把行号信息编入到文件中。比如对于下面的代码
#include <stdlib.h>
int main() {
const int array_count = 4;
int* p = malloc(array_count * sizeof(int));
p[array_count] = 0;
return 0;
}
如果我们使用O2参数让编译器去做优化
gcc -O2 mem_leak.c -o mem_leak
编译器会认为4~6行是没有意义的,于是被优化了。于是使用valgrind分析不出代码的问题
这并不是valgrind的错误,因为编译器的确编译出了一个空的main函数。我们可以用IDA反编译看看
所以我们要使用O0禁止编译优化
gcc -O0 mem_leak.c -o mem_leak
此时编译出来的二进制代码可以被解读为
此时使用valgrind分析,可以看到它给出内存写违例和内存泄露的报告。
但是它没有告诉我们哪行出错了,于是我们要加上-g编译参数
gcc -g -O0 mem_leak.c -o mem_leak
这样我们可以看到第6行导致写违例。
有时候,待分析的程序会启动子程序。如果我们希望分析子程序,则需要增加--trace-children=yes。比如我们使用time启动上面的程序
可以看出,valgrind分析出作为父程序的time是没有问题的,但是作为子程序的mem_leak有两个错误。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Tree - 103. Binary Tree Zigzag Level Order Traversal
- Tree - 107. Binary Tree Level Order Traversal II
- Trie - 212. Word Search II
- Trie - 211. Add and Search Word - Data structure design
- Trie - 208. Implement Trie (Prefix Tree)
- Tree - 337. House Robber III
- Tree - 250. Count Univalue Subtrees
- Tree - 124. Binary Tree Maximum Path Sum
- Tree - 110. Balanced Binary Tree
- Tree - 104. Maximum Depth of Binary Tree
- Tree - 298. Binary Tree Longest Consecutive Sequence
- Tree - 111. Minimum Depth of Binary Tree
- Tree - 129. Sum Root to Leaf Numbers
- Tree - 113. Path Sum II
- DFS&BFS - 200. Number of Islands