如何在不通过 valgrind 命令选项启动 Process 的每个实例的情况下对每个实例进行 valgrind memcheck

Posted

技术标签:

【中文标题】如何在不通过 valgrind 命令选项启动 Process 的每个实例的情况下对每个实例进行 valgrind memcheck【英文标题】:how do i valgrind memcheck on every instance of Process without starting it via valgrind command options 【发布时间】:2009-08-06 11:37:36 【问题描述】:

如何在不通过 valgrind 命令选项启动的情况下对 Process 的每个实例进行 valgrind memcheck。

有没有办法将监控选项保存在进程中,而不是每次都使用 valgrind 命令启动进程?

在 Microsoft Application Verifier 中,如果指定要监视应用程序,则该应用程序的任意数量的实例都会受到监视,无论它是子进程还是以其他方式启动。

有什么想法可以在 Valgrind 中做同样的事情吗?

我已经尝试了 valgrind memcheck 的 --trace-children=yes 选项...但是我的应用程序 xyz 向另一个应用程序 zzz 发出信号以启动 xyz(process) 的新实例,我想对其进行分析。在这种情况下,当 xyz 完成发送 zzz 信号时,valgrind 退出。它不会跟进 zzz 启动的进程。

谢谢, 维杰

【问题讨论】:

【参考方案1】:

IIRC,Valgrind 必须执行应用程序,因为它会更改只读符号以替换常见的库函数,如 malloc 等。

这意味着您不能将 memcheck 附加到已经运行的进程,因为它无法更改内存中程序的该部分(并且可能会破坏运行状态)。

可能还有其他原因。 quick google 建议您也不能将 memcheck 附加到正在运行的进程。如建议的那样,您可以将可执行文件包装在 bash 脚本中,例如。因此,如果程序myprog 创建了newprog 的新进程,则执行以下操作:

]$ mv /path/to/myprog /path/to/newprog

然后

#!/bin/bash
valgrind (options) /path/to/newprog $@

并称它为myprog $@ 确保参数被传递。然后,当您的程序使用myprog -a b -c d 创建一个新进程时,它会被包装在 valgrind 中。

这仅适用于某些 C 调用,例如 execve() 和其他调用,而其他创建进程的晦涩方式可能无法利用包装。

如果我错了,最好知道:)

【讨论】:

谢谢艾登,这是个好主意。我将尝试包装可执行文件以创建另一个传递参数的进程实例,如建议的那样,看看是否有帮助。谢谢,维杰【参考方案2】:

您能否将xyz 包装在一个批处理文件或另一个在 valgrind 中启动它的可执行文件中?

换句话说,将xyz 重命名为run_me_under_valgrind,然后创建一个新的xyz,在valgrind 下启动原来的run_me_under_valgrind

【讨论】:

【参考方案3】:

关于包装器可执行文件,我已经为 PostgreSQL 找到了以下脚本。 (我已经删除了各种特定于 postgres 的部分,例如发现提供的 valgrind 抑制文件)。

#!/bin/bash
set -e -u -x

# Pop top two elements from path; the first is added by pg_regress
# and the next is us.
function join_by  local IFS="$1"; shift; echo "$*"; 
IFS=':' read -r -a PATHA <<< "$PATH"
export PATH=$(join_by ":" "$PATHA[@]:2")

NEXT_POSTGRES=$(which postgres)
if [ "$NEXT_POSTGRES" -ef "./valgrind/postgres" ]; then
    echo "ERROR: attempt to execute self"
    exit 1
fi

echo "Running $NEXT_POSTGRES under Valgrind"

valgrind --leak-check=full --show-leak-kinds=definite,possible \
    --gen-suppressions=all --verbose --time-stamp=yes  \
    --log-file=valgrind-$$-%p.log --trace-children=yes \
    --track-origins=yes --read-var-info=yes --malloc-fill=8f \
    --free-fill=9f --num-callers=30 postgres "$@"

注意PATH 操作,以确保我们不会再次尝试从同一个地方执行postgres。在这种情况下,包装脚本也必须准确命名为 postgres,因此我必须确保它不会递归执行自身。

另一种方法是使用whatis -a 在路径中查找下一个可执行文件并直接运行它。但我发现这对我的用例造成了其他问题。


顺便说一句,如果您遇到类似

的错误
   valgrind: mmap(0x58000000, 2347008) failed in UME with error 22 (Invalid argument).
   valgrind: this can be caused by executables with very large text, data or bss segments.

...那么你很可能错误地试图在 valgrind 下运行 valgrind。

【讨论】:

以上是关于如何在不通过 valgrind 命令选项启动 Process 的每个实例的情况下对每个实例进行 valgrind memcheck的主要内容,如果未能解决你的问题,请参考以下文章

Linux 命令(143)—— valgrind 命令

我们如何在不使用 `psql` 的命令或选项的情况下显示集群中的所有数据库? [复制]

如何在 Linux (redhat) 上通过 gdb 在 xterm 中使用 valgrind?

ceph集群常用命令

如何用 Valgrind 检测使用 LuaJIT FFI 过程中的内存泄漏

MySQL的启动选项和系统变量该如何配置?