当前位置:网站首页>valgrind工具
valgrind工具
2022-07-28 05:26:00 【80岁艰难码字】
valgrind在ARM开发板上的交叉编译与运用
valgrind简介
借用valgrind的百度百科的解释:Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。而且它遵守GNU通用公共许可证条款,是一款自由软件。链接: valgrind官网.
内存的使用产生问题,对于偏向于嵌入式的程序员来说,是很难避免的。虽然靠编码规范,规矩的开发流程,严格的单元测试,以及自身的底子的实力程度能很大程度避开这些问题,但是遇到了,就最好从根源上解决。
valgrind包含很多工具,如下:
| 工具 | 作用 |
|---|---|
| Memcheck | 专门用于检测内存的问题,如:内存泄漏,内存覆盖,未初始化的内存的使用,越界访问等等 |
| Cachegrind | 主要用来检查程序中缓存使用时出现的问题 |
| Callgrind | 主要用来检查程序中函数调用过程中出现的问题 |
| Helgrind | 主要用来检查多线程程序中可能存在的竞争问题 |
| Massif | 主要用来检查程序中堆栈使用中存在的问题 |
| Extension | 通过core提供的功能,来编写特定的内存调试工具 |
本文着重于Memcheck的使用。
valgrind的交叉编译
环境:
目标机:ZLG的m1808核心板(基于Rockchip 的RK1808 AIoT处理器)
宿主机:Ubuntu18.04
源码:
首先在自己的开发宿主机上下载份最新的valgrind源码。
wget https://sourceware.org/pub/valgrind/valgrind-3.17.0.tar.bz2
配置:
1.先找到自己的交叉编译工具链的位置。然后进入解压后的valgrind-3.17.0中,执行以下命令:
./autogen.sh
./configure CC=xxx/aarch64-linux-gnu-gcc CXX=xxx/aarch64-linux-gnu-g++ LD=xxx/aarch64-linux-gnu-ld AR=xxx/aarch64-linux-gnu-ar --host=aarch64-linux --prefix=PATH
#其中xxx为交叉编译工具链的路径 "aarch64-linux"为configure文件中可选的选项(选择适合自己目标机的)
#PATH为编译后生成的文件存放位置
着重说明一点,按照其README给的建议,–prefix的路径最好与目标机中的位置一样,不然容易出现问题,比如:
“valgrind: failed to start tool ‘memcheck’ for platform ‘arm-linux’: No such file or directory”
这步配置完后,剩下的步骤很简单:
sudo make -j4
sudo make install
2.找到生成的文件,打包传入一样位置的路径中。如果不想传入一样的路径,那就在目标机的系统文件/etc/profile中添加:“export VALGRIND_LIB=/opt/valgrind-3.17.0/lib/valgrind
当然,还可以在其中PATH路径的”/usr/bin:/usr/sbin:/bin:"后面把“xxx/valgrind-3.17.0/bin”加上,执行下source /etc/profile ,就可以当valgrind命令使用了。
3.最后直接在目标机上任意位置输入命令:
valgrind --version
返回对应的版本号就成功了。否则,根据提示的信息找问题。如下图:
valgrind的memcheck的使用
–tool=< toolname > [default: memcheck] :toolname为选择的工具,默认为memecheck
–log-file= < filename >:filename 为日志输出的文件名。
————————————————————————————————————————
从官方文档看,对于memcheck使用,常用的有以下的选项指令:
–leak-check=<no|summary|yes|full> [default: summary]:
启用后,在客户端程序完成时搜索内存泄漏。如果设置为summary,则说明发生了多少泄漏。如果设置为full或 yes,则每个泄漏都将详细显示和/或计为错误,如选项–show-leak-kinds和 所指定 --errors-for-leak-kinds。如果–xml=yes给出,则memcheck将自动使用value --leak-check=full。–show-leak-kinds=none如果您对泄漏结果不感兴趣,可以使用减少xml输出的大小。
–leak-resolution=<low|med|high> [default: high]:
在执行泄漏检查时,确定为了将多个泄漏合并到一个泄漏报告中,Memcheck如何考虑将不同的回溯痕迹视为相同。设置为时low,仅前两个条目需要匹配。当med为时,必须匹配四个条目。当为时high,所有条目都必须匹配。
核心泄漏调试,您可能希望 --leak-resolution=high与–num-callers=40或如此多一起使用 。
请注意,该–leak-resolution设置不会影响Memcheck的发现泄漏的能力。它仅更改结果的显示方式。
–show-leak-kinds= [default: definite,possible]:
full 通过以下方式之一指定要在泄漏搜索中显示的泄漏类型:
用逗号分隔的一个或多个列表 definite indirect possible reachable。
all指定全套(所有泄漏种类)。等同于 --show-leak-kinds=definite,indirect,possible,reachable。
none 为空集。
–errors-for-leak-kinds= [default: definite,possible]:
指定要在full泄漏搜索中计为错误的泄漏种类 。的 指定方式类似于 --show-leak-kinds
–leak-check-heuristics= [default: all]:
指定在泄漏搜索期间要使用的一组泄漏检查启发式方法。启发式方法控制哪个内部指针指向一个块,使其被认为是可到达的。启发式集是通过以下方式之一指定的:
用逗号分隔的一个或多个列表 stdstring length64 newarray multipleinheritance。
all激活完整的启发式方法。等同于 --leak-check-heuristics=stdstring,length64,newarray,multipleinheritance。
none 为空集。
–show-reachable=<yes|no> , --show-possibly-lost=<yes|no>
这些选项提供了一种选择的方式来指定要显示的泄漏类型:
–show-reachable=no --show-possibly-lost=yes等同于 --show-leak-kinds=definite,possible。
–show-reachable=no --show-possibly-lost=no等同于 --show-leak-kinds=definite。
–show-reachable=yes等同于 --show-leak-kinds=all。
【注意,–show-possibly-lost=no如果–show-reachable=yes指定,则无效。】
–undef-value-errors=<yes|no> [default: yes]:
控制Memcheck报告是否使用未定义的值错误。no如果您不想看到未定义的值错误,请将此设置为 。它还具有一定程度加快Memcheck速度的副作用。AddrCheck(在Valgrind 3.1.0中删除)的功能类似于Memcheck(带有) --undef-value-errors=no。
–track-origins=<yes|no> [default: no]:
控制Memcheck是否跟踪未初始化值的来源。默认情况下,它不是,这意味着,尽管它可以告诉您未初始化的值正在以危险的方式使用,但是它无法告诉您未初始化的值是从哪里来的。这通常使得很难找到根本问题。
设置yes为时,Memcheck会跟踪所有未初始化值的来源。然后,当报告未初始化的值错误时,Memcheck将尝试显示值的来源。源可以是以下四个位置之一:堆块,堆栈分配,客户端请求或其他各种源(例如的调用brk)。
对于源自堆块的未初始化值,Memcheck将显示该块的分配位置。对于源自堆栈分配的未初始化值,Memcheck可以告诉您哪个函数分配了该值,但仅此而已-通常它会向您显示该函数的左括号的源位置。因此,您应该仔细检查函数的所有局部变量是否已正确初始化。
请注意,组合 --track-origins=yes 和–undef-value-errors=no是荒谬的。Memcheck在启动时会检查并拒绝此组合。
使用示例:
void func(void)
{
float* t = (float*)malloc(sizeof(float)*4);
float* p = t;
for(int i=0; i<4;i++){
p++;
}
*p =4.4; //未分配内存,无效的写入
printf("%f\n",*p); //无效的读出
//t指针未释放!
}
int main(void)
{
func();
return 0;
}
结果如下图:
如愿的检查出三处地方:
- “Invalid write of size 4”:无效的写入。
- “Invalid read of size 4”:无效的读出。
- “16 byte in 1blocks are definitely lost…”:确定地泄漏了16字节。
总的来说,valgrind对于项目上内存问题地检测还是不小的帮助,可以较快速地定位问题。
边栏推荐
猜你喜欢
随机推荐
error: redefinition of ‘xxx‘
【学习笔记】线程创建
error: redefinition of ‘xxx‘
小程序:生命周期
自定义组件--纯数据字段&组件的生命周期
Treasure plan TPC system development DAPP construction
用c语言实现三子棋小游戏
微信小程序自定义编译模式
2022-07-17 达梦数据库安装
2022-06-07 六.日志实现
set_ multicycle_ path
Several methods of QT setting loading interface
JSP实现文件上传功能的同时还要向后台传递参数
小程序自定义组件-数据,方法和属性
如何模拟实现strcpy库函数
2022-06-07 ResponseBodyAdvice导致Swagger出现弹框问题
qt中Qthread线程的使用以及安全关闭
【学习笔记】驱动
【自我救赎的开始】
MFC 使用控制台打印程序信息








