简介
Valgrind
是构建动态分析工具的框架,Valgrind
工具可以自动检测许多内存管理和线程错误,并详细介绍您的程序,还可以使用Valgrind
构建新工具。
官网:http://valgrind.org/
valgrind的使用:http://valgrind.org/docs/manual/manual.html
下载地址:git clone git://sourceware.org/git/valgrind.git
交叉编译
查看README.aarch64
和README.android
文件:
1 | Building |
参照上面的做法,开始交叉编译:
1 | mkdir out |
编译生成的文件放在./out
目录下:
1 | victor@victor-HP:~/disk2/work2/util/valgrind# ll out/ |
拷贝到目标板子上
1、拷贝方法一:
将编译出来的out/
目录整个拷贝到目标板子上,比如说拷贝到目标板子的/var/
目录下,然后设置环境变量export VALGRIND_LIB="/out/bin/lib/valgrind"
,设置完毕后就可以进入到cd /var/bin/bin
目录下开始执行valgrind
命令。
如果这里不执行设置环境变量,运行valgrind
会出现如下错误:
1 | valgrind: failed to start tool 'memcheck' for platform 'arm-linux': No such file or directory |
2、拷贝方法二:
将生成的 bin/
、include/
、lib/
三个文件的内容放到目标板子上对应的位置,就可以直接执行valgrind
命令了。
运行
在板子上执行如下命令测试应用程序:./valgrind --leak-check=full /var/test_app
,正常情况下,就能够开始检查并输出结果,但是我的这边执行结果如下:
1 | Fatal error at startup: a function redirection |
按照上面的提示,就是说ld-linux-aarch64.so.1
文件不带debuginfo的,也就是stripped
的,调试信息已经被剥离,所以valgrind
无法运行。果然,找到板子上的ld-linux-aarch64.so.1
执行file
命令,看到的结果是stripped
。
1 | # file ld-linux-aarch64.so.1 |
关于stripped
和not-stripped
的区别在:
https://unix.stackexchange.com/questions/2969/what-are-stripped-and-not-stripped-executables-in-unix
1 | If you compile an executable with gcc's -g flag, it contains debugging information. |
解决方法一
按照提示,我们需要使用到not-stripped
的ld-linux-aarch64.so.1
文件,刚好看到yocto上有编译出valgrind
,lib文件放在tmp/work/aarch64-poky-linux/valgrind/3.13.0-r0/recipe-sysroot/lib
目录下,查看到ld-linux-aarch64.so.1
的文件类型是not stripped
类型,符合我们的要求。
1 | # file ld-linux-aarch64.so.1 |
解决方法就是将其拷贝到目标板子上,当然,这里不单单是要拷贝ld-linux-aarch64.so.1
文件,也要拷贝libc.so.6
和libc-2.27.so
文件。
当然,这个只是临时的测试方法,最最根据的解决办法还是在系统中编译出带not stripped
的文件。
解决方法二
因为yocto有现成编译好的valgrind
,所以我们之间将tmp/work/aarch64-poky-linux/valgrind/3.13.0-r0/image/
生成的可执行文件和库之间拷贝到目标板子上,参照上面的拷贝方法,此方法可以顺利的运行,不需要用到not-stripped
类型的ld-linux-aarch64.so.1
文件。
这里遗留了一个问题,就是yocto编译的valgrind
和我们自己交叉编译出来的valgrind
对ld-linux-aarch64.so.1
文件stripped
和not stripped
的依赖程度不一样。yocto不需要not stripped
的,而我们自己交叉编译出来的需要。
再次运行
我们准备了一个测试程序test_app
,如下,这个程序有malloc
但是没有free
,保证会内存泄露。
1 | #include <stdio.h> |
使用valgrind
运行检查test_app
程序:
1 | @android:/var/out/bin # ./valgrind --leak-check=full /var/test_app |
从上面可以很清楚的看出,出现了50个字节的内存泄露,泄露位置在test_app.c
的第7行。其中0x40060F
为堆栈信息,可以通过objdump
反汇编出来,比如说:aarch64-poky-linux-objdump -d -l -f -g -S test_app > test_app_objdump.txt
,或者使用addr2line
查看代码所在位置aarch64-poky-linux-addr2line -e test_app 0x40060F
。如果addr2line
出来的结果是??:0
,可以去解析带not stripped
的test_app
的二进制文件,通常放在out/target/xxx/yyy/symbol/
文件下。
可能出现的错误
如果在运行valgrind
一直刷新如下log,可以使用带--undef-value-errors=no
的参数进行过滤。
1 | ==56903== Use of uninitialised value of size 8 |
参考资料:
内存、性能问题分析的利器——valgraind
内存问题分析的利器——valgraind的memcheck
valgrind 工具介绍和简单的使用