arm linux下交叉编译valgrind工具进行内存泄露检测和性能分析

C/C++等底层语言在提供强大功能及性能的同时,其灵活的内存访问也带来了各种纠结的问题。如果crash的地方正是内存使用错误的地方,说明你人品好。如果crash的地方内存明显不是consistent的,或者内存管理信息都已被破坏,编译器不能发现这些问题,.运行时才能捕获到这些错误并且还是随机出现的,那就比较麻烦了。当然,祼看code打log是一个办法,但其效率不是太高,尤其是在运行成本高或重现概率低的情况下。另外,静态检查也是一类方法,有很多工具(lint, cppcheck, klockwork, splint, etc.)。但缺点是误报很多,不适合针对性问题。另外好点的一般还要钱。最后,就是动态检查工具。下面介绍几个Linux平台下主要的运行时内存检查工具。绝大多数都是开源免费且支持x86和ARM平台的。

首先,比较常见的内存问题有下面几种:
• memory overrun:写内存越界(越界访问堆、栈和全局变量)
• double free:同一块内存释放两次
• use after free:内存释放后使用
• wild free:释放内存的参数为非法值
• access uninitialized memory:访问未初始化内存
• read invalid memory:读取非法内存,本质上也属于内存越界
• memory leak:内存泄露
• use after return:caller访问一个指针,该指针指向callee的栈内内存
• stack overflow:栈溢出

针对上面的问题,主要有以下几种方法:
1. 为了检测内存非法使用,需要hook内存分配和操作函数。hook的方法可以是用C-preprocessor,也可以是在链接库中直接定义(因为Glibc中的malloc/free等函数都是weak symbol),或是用LD_PRELOAD。另外,通过hook strcpy(),memmove()等函数可以检测它们是否引起buffer overflow。
2. 为了检查内存的非法访问,需要对程序的内存进行bookkeeping,然后截获每次访存操作并检测是否合法。bookkeeping的方法大同小异,主要思想是用shadow memory来验证某块内存的合法性。至于instrumentation的方法各种各样。有run-time的,比如通过把程序运行在虚拟机中或是通过binary translator来运行;或是compile-time的,在编译时就在访存指令时就加入检查操作。另外也可以通过在分配内存前后加设为不可访问的guard page,这样可以利用硬件(MMU)来触发SIGSEGV,从而提高速度。
3. 为了检测栈的问题,一般在stack上设置canary,即在函数调用时在栈上写magic number或是随机值,然后在函数返回时检查是否被改写。另外可以通过mprotect()在stack的顶端设置guard page,这样栈溢出会导致SIGSEGV而不至于破坏数据。

以下是几种常用工具在linux x86_64平台的实验结果,注意其它平台可能结果有差异。

Tool\Problem memory overrun double free use after free wild free access uninited read invalid memory memory leak use after return stack overflow
Memory checking tools in Glibc   Yes   Yes     Yes   Yes(if use memcpy, strcpy, etc)
Valgrind Yes Yes Yes Yes Yes Yes Yes Yes Yes
Memwatch   Yes   Yes     Yes    
Dmalloc Yes Yes Yes Yes     Yes    
 下面简单介绍一下这些工具以及基本用法。更详细用法请参见各自manual。

valgrind通常用来成分析程序性能及程序中的内存泄露等错误

一 Valgrind工具集介绍

Valgrind包含下列工具:

    1、memcheck:检查程序中的内存问题,如泄漏、越界、非法指针等。

    2、callgrind:检测程序代码的运行时间和调用过程,以及分析程序性能。

    3、cachegrind:分析CPU的cache命中率、丢失率,用于进行代码优化。

    4、helgrind:用于检查多线程程序的竞态条件。

    5、massif:堆栈分析器,指示程序中使用了多少堆内存等信息。

这几个工具的使用是通过命令:valgrand --tool=name 程序名来分别调用的,当不指定tool参数时默认是 --tool=memcheck

二 Valgrind工具详解

1.Memcheck

    最常用的工具,用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc、free、new、delete的调用都会被捕获。所以,它能检测以下问题:

       1、对未初始化内存的使用;

       2、读/写释放后的内存块;

       3、读/写超出malloc分配的内存块;

       4、读/写不适当的栈中内存块;

       5、内存泄漏,指向一块内存的指针永远丢失;

       6、不正确的malloc/free或new/delete匹配;

       7、memcpy()相关函数中的dst和src指针重叠。

这些问题往往是C/C++程序员最头疼的问题,Memcheck能在这里帮上大忙。
例如:

[plain]  view plain copy
  1. #include <stdlib.h>  
  2. #include <malloc.h>  
  3. #include <string.h>  
  4.   
  5. void test()  
  6. {  
  7.     int *ptr = malloc(sizeof(int)*10);  
  8.   
  9.     ptr[10] = 7; // 内存越界  
  10.   
  11.     memcpy(ptr +1, ptr, 5); // 踩内存  
<think>好的,用户现在想了解在Linux下如何交叉编译安装Valgrind。首先,我需要回忆交叉编译的基本概念,就是在一个平台上编译生成另一个平台的可执行程序。Valgrind本身是一个强大的内存调试工具,通常用于检测内存泄漏、越界访问等问题。但用户可能需要将它移植到不同的架构,比如ARM或MIPS上,这需要交叉编译。 接下来,我需要确定用户的需求。用户可能正在开发嵌入式系统,或者在目标平台上无法直接编译Valgrind,所以需要交叉编译。这时候,用户可能需要指导如何配置交叉编译环境,设置正确的工具链,并处理可能的依赖问题。 然后,我需要考虑交叉编译Valgrind的具体步骤。通常步骤包括:安装交叉编译工具链,下载Valgrind源码,配置编译选项,指定目标架构工具链路径,然后进行编译安装。同时,需要注意Valgrind可能依赖的库是否也在目标平台上存在,或者是否需要同样交叉编译这些依赖库。 另外,用户可能遇到的问题包括配置错误、依赖缺失、工具链不兼容等。例如,如果交叉编译工具链没有正确设置路径,或者缺少必要的头文件库文件,编译过程可能会失败。需要提示用户检查工具链的安装,环境变量如CC、CXX的设置是否正确,以及是否指定了正确的--host参数。 还需要考虑Valgrind的版本是否支持目标平台。某些较旧的Valgrind版本可能不支持最新的架构或工具链,建议用户使用较新的版本,或者查看官方文档的兼容性说明。 另外,用户可能需要将编译好的Valgrind移植到目标平台,因此需要说明如何将生成的可执行文件库文件复制到目标系统,并设置相应的权限环境变量。同时,提醒用户在目标平台上运行时可能需要的内核配置,例如是否启用了必要的调试支持。 最后,可能需要给出验证步骤,例如在目标平台上运行Valgrind的基本命令,检查是否能正常工作。如果遇到问题,如何调试,比如查看日志,确认动态链接库是否正确等。 总结起来,我需要分步骤详细说明交叉编译Valgrind的过程,包括环境准备、配置、编译、安装验证,同时提醒可能出现的常见问题及解决方法,确保用户能够顺利完成交叉编译并在目标平台上使用Valgrind进行内存调试。</think>在 Linux交叉编译 Valgrind 需要为目标架构(如 ARM、MIPS 等)配置专用工具链。以下是详细步骤注意事项: --- ### 一、准备工作 1. **安装交叉编译工具链** - 根据目标平台安装对应的工具链(示例以 ARM 为例): ```bash # Debian/Ubuntu 安装 ARM 工具链 sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf ``` 2. **下载 Valgrind 源码** ```bash wget https://sourceware.org/pub/valgrind/valgrind-3.22.0.tar.bz2 tar -xjvf valgrind-3.22.0.tar.bz2 cd valgrind-3.22.0 ``` --- ### 二、配置交叉编译环境 1. **设置工具链变量** ```bash # 指定交叉编译器前缀(以 ARM 为例) export CC=arm-linux-gnueabihf-gcc export CXX=arm-linux-gnueabihf-g++ ``` 2. **配置编译参数** ```bash ./configure \ --host=arm-linux-gnueabihf \ # 目标平台架构 --prefix=/opt/valgrind-arm # 安装路径 ``` - **关键选项**: - `--host`:指定目标平台(必须与工具链匹配)。 - `--prefix`:定义安装路径(方便移植到目标设备)。 3. **解决依赖问题** - 若提示缺少依赖库(如 `libc`),需确保目标平台的 `sysroot` 已配置: ```bash ./configure ... --with-sysroot=/path/to/target-sysroot ``` --- ### 三、编译与安装 1. **编译源码** ```bash make -j$(nproc) # 使用多核加速编译 ``` 2. **安装到指定目录** ```bash make install ``` - 生成的二进制文件位于 `/opt/valgrind-arm/bin`。 --- ### 四、移植到目标平台 1. **复制文件到目标设备** ```bash scp -r /opt/valgrind-arm root@target-device:/opt/ ``` 2. **设置环境变量(在目标设备上)** ```bash export PATH=/opt/valgrind-arm/bin:$PATH ``` --- ### 五、验证与使用 1. **检查 Valgrind 版本** ```bash # 在目标设备上执行 valgrind --version ``` 2. **运行内存检测** ```bash valgrind --leak-check=full ./your_program ``` --- ### 常见问题解决 1. **错误:`Unsupported platform`** - 原因:Valgrind 版本不支持目标架构。 - 解决:使用最新版 Valgrind 或检查[官方支持列表](https://valgrind.org/docs/manual/manual-core.html#manual-core.platform)。 2. **动态链接库缺失** - 在目标设备上安装依赖库: ```bash # Debian/Ubuntu 目标设备 sudo apt-get install libc6-armhf-cross ``` 3. **内核配置问题** - 确保目标设备的 Linux 内核启用了调试支持: ```bash CONFIG_DEBUG_INFO=y # 启用调试符号 CONFIG_DEBUG_KERNEL=y # 内核调试支持 ``` --- ### 附:交叉编译工具链查询 - 查看工具链支持的架构: ```bash arm-linux-gnueabihf-gcc -dumpmachine # 输出示例:arm-linux-gnueabihf ``` --- 通过以上步骤,你可以将 Valgrind 交叉编译并部署到嵌入式或非 x86 架构的设备上,用于内存调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值