使用和了解Valgrind核心:高级主题

本章介绍了Valgrind核心服务的高级方面,主要是为希望以某些有用的方式自定义和修改Valgrind的默认行为的用户感兴趣。涵盖的主题是:

  • “客户请求”机制

  • 使用Valgrind的gdbserver和GDB调试程序

  • 功能包装

3.1。客户端请求机制

Valgrind具有一个陷门机制,通过该机制,客户端程序可以将所有方式的请求和查询传递给Valgrind和当前工具。在内部,这广泛用于使各种事情发挥作用,尽管从外部看不到。

为了方便起见,提供了这些所谓的客户端请求的一部分,以便您可以告诉Valgrind有关程序行为的事实,也可以进行查询。特别是,您的程序可以告诉Valgrind有关其他方面不会知道的事情,从而获得更好的结果。

客户端需要包含头文件才能使其工作。哪个头文件取决于您使用的客户端请求。一些客户端请求由内核处理,并在头文件中定义valgrind/valgrind.h。工具特定的头文件以工具命名,例如 valgrind/memcheck.h。每个特定于工具的头文件都包含在内valgrind/valgrind.h,因此如果您包含特定于工具的头,则不需要将其包含在客户端中。所有头文件可以在安装include/valgrindValgrind的目录中找到。

这些头文件中的宏具有魔术属性,它们可以生成Valgrind可以发现的代码。但是,代码在Valgrind上运行时不执行任何操作,因此您不会因为使用此文件中的宏而被迫在Valgrind下运行程序。此外,您不需要将程序与任何额外的支持库链接。

添加到您的二进制代码的代码可以忽略不计的性能影响:在x86,amd64,ppc32,ppc64和ARM上,开销是6个简单的整数指令,除非是紧密循环,否则可能无法检测。但是,如果您真的希望编译客户端请求,可以使用-DNVALGRIND(类似于 -DNDEBUG“效果” assert)进行编译。

我们鼓励您将标题复制valgrind/*.h到项目的包含目录中,这样您的程序就没有编译时依赖于正在安装的Valgrind。Valgrind标题与其他代码大部分不同,是BSD风格的许可证,所以您可以不必担心许可证不兼容。

以下是对可用宏的简要说明 valgrind.h,可以使用多种工具(请参阅特定于工具的文档以了解工具特定的宏)。

RUNNING_ON_VALGRIND

如果在Valgrind上运行,则返回1,如果在实际CPU上运行则返回0。如果您运行Valgrind本身,则返回您运行的Valgrind仿真层数。

VALGRIND_DISCARD_TRANSLATIONS

丢弃指定地址范围内的代码翻译。如果您正在调试JIT编译器或其他动态代码生成系统,则很有用。在此调用之后,尝试在无效地址范围内执行代码将导致Valgrind对该代码进行新的翻译,这可能是您想要的语义。请注意,代码无效是昂贵的,因为快速找到所有相关的翻译是非常困难的,所以尽量不要经常打电话。请注意,您可以很聪明:只有当以前包含代码的区域被新的代码覆盖时,才需要调用它。您可以选择将代码写入新鲜的内存,并且偶尔调用这些代码一次丢弃大量的旧代码。

或者,对于ppc32 --smc-check=all/ Linux,ppc64 / Linux或ARM / Linux 的透明自修改代码支持,使用或运行。

VALGRIND_COUNT_ERRORS

返回Valgrind到目前为止发现的错误数。与--log-fd=-1选项结合使用时,可用于测试工具代码 ; 这个默认运行Valgrind,但客户端程序可以检测何时发生错误。仅对报告错误的工具有用,例如它对Memcheck有用,但对于Cachegrind,它总是返回零,因为Cachegrind不报告错误。

VALGRIND_MALLOCLIKE_BLOCK

如果您的程序管理自己的内存,而不是使用标准的mallocnewnew[],则跟踪有关堆块的信息的工具不会做得很好。例如,Memcheck将不会检测到几乎相同的错误,并且错误消息将不会提供信息。为了改善这种情况,在您的自定义分配器分配一些新内存之后使用此宏。有关valgrind.h如何使用它的信息,请参阅注释 。

VALGRIND_FREELIKE_BLOCK

这应该与之配合使用 VALGRIND_MALLOCLIKE_BLOCK。再次看看valgrind.h有关如何使用它的信息。

VALGRIND_RESIZEINPLACE_BLOCK

通知Valgrind工具,分配的块的大小已被修改,但不是其地址。查看valgrind.h有关如何使用它的更多信息。

VALGRIND_CREATE_MEMPOOL, VALGRIND_DESTROY_MEMPOOL, VALGRIND_MEMPOOL_ALLOC, VALGRIND_MEMPOOL_FREE, VALGRIND_MOVE_MEMPOOL, VALGRIND_MEMPOOL_CHANGE, VALGRIND_MEMPOOL_EXISTS

这些类似于 VALGRIND_MALLOCLIKE_BLOCK和 VALGRIND_FREELIKE_BLOCK ,但偏向于使用内存池的代码定制。有关详细说明,请参阅 内存池

VALGRIND_NON_SIMD_CALL[0123]

在客户端程序中执行实际 CPU 上的功能 ,而不是Valgrind正常运行代码的虚拟CPU。该函数必须采用一个整数(保持线程ID)作为第一个参数,然后将0,1,2或3个参数(取决于使用哪个客户端请求)。这些在Valgrind内部以各种方式使用。它们可能对客户端程序有用。

警告:只有使用这些,如果你 真的知道你在做什么。它们并不完全可靠,可能导致Valgrind崩溃。查看 valgrind.h更多详情。

VALGRIND_PRINTF(format, ...)

将Printf样式的消息打印到Valgrind日志文件。该消息以一对**标记之间的PID为前缀 。(与所有客户端请求一样,如果客户端程序未在Valgrind下运行,则不会输出任何内容。)直到遇到换行符或后续的Valgrind输出打印时才会产生输出; 这允许您通过多个呼叫建立单行输出。返回输出的字符数,不包括PID前缀。

VALGRIND_PRINTF_BACKTRACE(format, ...)

喜欢VALGRIND_PRINTF(特别是返回值是相同的),但是之后立即打印一个堆栈回溯。

VALGRIND_MONITOR_COMMAND(command)

执行给定的monitor命令(一个字符串)。如果识别到命令,则返回0。如果无法识别命令,则返回1。请注意,某些监视器命令提供对通过特定客户端请求可访问的功能的访问。例如,可以使用VALGRIND_DO_LEAK_CHECK或通过监视器命令“leak_search”从客户端程序请求memcheck泄漏搜索。请注意,命令字符串的语法仅在运行时验证。因此,如果存在,最好使用特定的客户端请求对参数进行更好的编译时验证。

VALGRIND_STACK_REGISTER(start, end)

注册一个新的堆栈。通知Valgrind,start和end之间的内存范围是唯一的堆栈。返回可与其他VALGRIND_STACK_*调用一起使用的堆栈标识符 。

Valgrind将使用此信息来确定堆栈指针的更改是否是推送到堆栈上的项目或更改为新堆栈。如果您正在使用用户级线程包,并注意到堆栈跟踪记录中的崩溃或Valgrind关于未初始化内存读取的虚假错误,请使用此方法。

警告:不幸的是,这个客户端请求是不可靠的,最好避免。

VALGRIND_STACK_DEREGISTER(id)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值