有人可以提供有关 Valgrind 工作原理的快速顶级解释吗?一个例子:它如何知道何时分配和释放内存?
5 回答
Valgrind 基本上在“沙箱”中运行您的应用程序。在此沙箱中运行时,它能够插入自己的指令来进行高级调试和分析。
从手册:
然后,您的程序将在 Valgrind 内核提供的合成 CPU 上运行。当新代码第一次执行时,核心将代码交给选定的工具。该工具将其自己的检测代码添加到其中并将结果返回给核心,该核心协调该检测代码的继续执行。
所以基本上,valgrind 提供了一个虚拟处理器来执行你的应用程序。但是,在处理您的应用程序指令之前,它们会被传递给工具(例如 memcheck)。这些工具有点像插件,它们能够在您的应用程序在处理器上运行之前对其进行修改。
这种方法的好处是您根本不需要修改或重新链接您的程序即可在 valgrind 中运行它。它确实会导致您的程序运行速度变慢,但是 valgrind 并不是为了测量性能或在您的应用程序正常执行期间运行,所以这不是一个真正的问题。
Valgrind 是一个动态二进制分析 (DPA) 工具,它使用动态二进制检测 (DPI) 框架来检查内存分配、检测死锁和分析应用程序。DPI 框架有自己的低级内存管理器、调度器、线程处理程序和信号处理程序。Valgrind 工具套件包括类似的工具
- Memcheck - 动态跟踪内存分配并报告内存泄漏。
- Helgrind - 检测并报告死锁、潜在的数据竞争和锁反转。
- Cachegrind - 模拟应用程序如何与系统缓存交互并提供有关缓存未命中的信息。
- Nulgrind - 一个从不进行任何分析的简单 valgrind。开发人员用于性能基准测试。
- Massif - 一种分析应用程序堆内存使用情况的工具。
Valgrind 工具使用反汇编和重新合成机制,将应用程序加载到进程中,反汇编应用程序代码,添加用于分析的检测代码,将其组装回来并执行应用程序。它使用 Just Intime Compiler (JIT) 将应用程序与检测代码一起嵌入。
Valgrind Tool = Valgrind Core + Tool Plugin
Valgrind Core 反汇编应用程序代码并将代码片段传递给工具插件以进行检测。工具插件添加分析代码并将其组装回来。因此,Valgrind 提供了在 Valgrind 框架之上编写我们自己的工具的灵活性。Valgrind 使用影子寄存器和影子内存来检测读/写指令、读/写系统调用、堆栈和堆分配。
Valgrind 为系统调用提供包装器,并为每个系统调用的前后回调注册,以跟踪作为系统调用的一部分访问的内存。因此,Valgrind 是 Linux 操作系统和客户端应用程序之间的操作系统抽象层。
该图说明了 Valgrind 的 8 个阶段:
valgrind 位于您的程序和操作系统之间的一层,拦截对操作系统请求内存(解除)分配的调用,并在实际分配内存并传回等效内存之前记录正在操作的内容。它本质上是大多数代码分析器的工作方式,除了在低得多的级别(系统调用而不是程序函数调用)。
在这里您可以找到一些不错的信息:
除了熟悉 LD_PRELOAD。
Valgrind 基本上是一个执行程序的虚拟机。它是一种虚拟架构,可以拦截每个分配/释放内存的调用。