【发布时间】:2017-05-26 05:59:52
【问题描述】:
我正在调试一个仅在我的程序的 PPC64 端口中出现的问题。
我有一个测试用例,其中 C 库 qsort 被赋予一个 libffi 生成的闭包作为字符串比较回调。字符串正确传递给回调,返回值精确存储到libffi传递给闭包函数的返回值缓冲区中。
但是,数组未按qsort 正确排序。此外,Valgrind 报告 C 库 qsort 代码正在访问未初始化的内存,--track-orgins=yes 显示该内存是由 Libffi 堆栈分配的。我强烈怀疑这是返回值,因此由于垃圾比较,排序不正确。
即Libffi 为返回值分配了缓冲区,并将该值传播给回调调用者;但是我的闭包调度函数被赋予了错误的指针,因此没有将返回值放在正确的位置。
出于某种奇怪的原因,Valgrind 不报告未初始化内存的地址,只报告代码中使用的位置和分配的位置。
我只是想将该位置的地址与传递给闭包函数的指针进行比较:它们甚至是远程关闭的吗?
有没有办法从 Valgrind 获取这些信息?
更新:我正在使用没有 root 权限的 GCC Compile Farm 机器;安装的 libffi 没有调试信息。它是 3.0.13 版本。
但是,我刚刚构建的 libffi git 头会重现此问题。
我已经确认是未初始化的返回值区。
我在闭包调度汇编代码ffi_closure_LINUX64 中添加了一条指令,用于在闭包调度堆栈帧的RETVAL 部分的底部初始化一个双字大小的区域。这使得 Valgrind 错误消失了;但当然返回值是垃圾。它还证实了一个基本的理智:调用闭包调度助手之前的代码和之后的代码引用相同的返回值区域。 (堆栈指针没有意外移动,并且帧引用是正确的。)只是用户代码最终获得的地址并不指向该返回值。
接下来,我将返回区域的初始化向下移动到名为ffi_closure_helper_LINUX64 的 C 函数中,靠近函数的入口。这也仍然使未初始化的错误消失,确认助手通过%r6(参数4)获取正确的返回值区域地址。
【问题讨论】:
-
您使用的是哪个版本的 Valgrind?在什么操作系统上?
-
@PaulFloyd 好点。 Valgrind 是 3.9.0,在带有 Glibc 2.18 的 Fedora 系统上。
-
可以用3.12吗? (3.13即将发布)
-
@PaulFloyd 我现在正在通过 libffi 调试它,使用 git head。