在 PHP 7.4 中使用 FFI 加载库时出现问题
Problem loading a library with FFI in PHP 7.4
我在 PHP 中将第三方 .so 库与新的 FFI 一起使用时遇到问题。
当我 运行 这段代码时:
<?php
$ffi = FFI::cdef('typedef int (*NFE_Nome)(const char* sNome, int* esTamanho);', 'libacbrnfe64.so');
PHP 输出这个错误:
double free or corruption (out)
Aborted (core dumped)
这是库本身、我的 PHP 配置或其他问题吗?这让我感到困惑,因为我通常可以将同一个库与此 C++ 代码一起使用:
#include <iostream>
#include <dlfcn.h>
typedef int (*NFE_Nome)(const char* sNome, int* esTamanho);
#define BUFFER_LEN 256
int main() {
void *lib = dlopen("libacbrnfe64.so", RTLD_LAZY);
auto libMethod = (NFE_Nome) dlsym(lib, "NFE_Nome");
const std::string bufferNome(BUFFER_LEN, ' ');
int bufferNomeLength = BUFFER_LEN;
libMethod(bufferNome.c_str(), &bufferNomeLength);
std::cout << bufferNome << std::endl;
return 0;
}
我知道 PHP 代码不执行 NFE_Nome 函数,但我在尝试调用函数本身之前遇到错误。
-- 编辑--
这个问题是两个不同程序中的两个错误造成的。
链接共享对象时,fpc-3.0.0(或更新版本)将此添加到依赖项(作为第一个依赖项):/lib64/ld-linux-x86-64.so.2
ld-linux-x86-64.so.2 导出一个 calloc
变体,它不会(总是)清除内存 returns(详情如下)
OP 建议的解决方法是在单独的传递中链接(使用 fpc
的 -E
(或 -Cn
)选项),但在 运行 [=19= 之前] 修复 link.res
文件。为此,我破解了这个 awk 脚本,但我确实觉得它有点笨拙:
#!/usr/bin/awk -f
[=10=]=="INPUT(" { state=1; next; }
[=10=]=="/lib64/ld-linux-x86-64.so.2" { state=2; next; }
[=10=]==")" && state>0 { state=0;next; }
state==1 { print "INPUT("; state=0; }
{ print [=10=]; }
-- 原答案--
听起来像是一个链接问题:您可能已经将 /lib64/ld-linux-x86-64.so.2
添加到依赖的共享库中,这既不需要也没有用。
实际上,它产生了一个 calloc
版本,returns 内存未归零。此处描述了详细信息:https://www.linuxquestions.org/questions/programming-9/debugging-dlopen-4175668676/ and here:
建议解决方案:根据示例更改链接:
- gcc -shared -o demodule.so demodule.o /lib64/ld-linux-x86-64.so.2 -lglib-2.0
+ gcc -shared -o demodule.so demodule.o -lglib-2.0
可以使用 readelf -d
检查差异。错误:
Dynamic section at offset 0x828 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
右输出:
Dynamic section at offset 0x7f8 contains 25 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
此外,使用命令 ldd demodule.so
包含 /lib64/ld-linux-x86-64.so.2
的行应该是最后一行。
编辑:sourceware.org 上关于此问题的讨论:
https://sourceware.org/bugzilla/show_bug.cgi?id=25486
编辑:在 Freepascal 方面:https://bugs.freepascal.org/view.php?id=36706
我在 PHP 中将第三方 .so 库与新的 FFI 一起使用时遇到问题。 当我 运行 这段代码时:
<?php
$ffi = FFI::cdef('typedef int (*NFE_Nome)(const char* sNome, int* esTamanho);', 'libacbrnfe64.so');
PHP 输出这个错误:
double free or corruption (out)
Aborted (core dumped)
这是库本身、我的 PHP 配置或其他问题吗?这让我感到困惑,因为我通常可以将同一个库与此 C++ 代码一起使用:
#include <iostream>
#include <dlfcn.h>
typedef int (*NFE_Nome)(const char* sNome, int* esTamanho);
#define BUFFER_LEN 256
int main() {
void *lib = dlopen("libacbrnfe64.so", RTLD_LAZY);
auto libMethod = (NFE_Nome) dlsym(lib, "NFE_Nome");
const std::string bufferNome(BUFFER_LEN, ' ');
int bufferNomeLength = BUFFER_LEN;
libMethod(bufferNome.c_str(), &bufferNomeLength);
std::cout << bufferNome << std::endl;
return 0;
}
我知道 PHP 代码不执行 NFE_Nome 函数,但我在尝试调用函数本身之前遇到错误。
-- 编辑--
这个问题是两个不同程序中的两个错误造成的。
链接共享对象时,fpc-3.0.0(或更新版本)将此添加到依赖项(作为第一个依赖项):
/lib64/ld-linux-x86-64.so.2
ld-linux-x86-64.so.2 导出一个
calloc
变体,它不会(总是)清除内存 returns(详情如下)
OP 建议的解决方法是在单独的传递中链接(使用 fpc
的 -E
(或 -Cn
)选项),但在 运行 [=19= 之前] 修复 link.res
文件。为此,我破解了这个 awk 脚本,但我确实觉得它有点笨拙:
#!/usr/bin/awk -f
[=10=]=="INPUT(" { state=1; next; }
[=10=]=="/lib64/ld-linux-x86-64.so.2" { state=2; next; }
[=10=]==")" && state>0 { state=0;next; }
state==1 { print "INPUT("; state=0; }
{ print [=10=]; }
-- 原答案--
听起来像是一个链接问题:您可能已经将 /lib64/ld-linux-x86-64.so.2
添加到依赖的共享库中,这既不需要也没有用。
实际上,它产生了一个 calloc
版本,returns 内存未归零。此处描述了详细信息:https://www.linuxquestions.org/questions/programming-9/debugging-dlopen-4175668676/ and here:
建议解决方案:根据示例更改链接:
- gcc -shared -o demodule.so demodule.o /lib64/ld-linux-x86-64.so.2 -lglib-2.0
+ gcc -shared -o demodule.so demodule.o -lglib-2.0
可以使用 readelf -d
检查差异。错误:
Dynamic section at offset 0x828 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
右输出:
Dynamic section at offset 0x7f8 contains 25 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
此外,使用命令 ldd demodule.so
包含 /lib64/ld-linux-x86-64.so.2
的行应该是最后一行。
编辑:sourceware.org 上关于此问题的讨论: https://sourceware.org/bugzilla/show_bug.cgi?id=25486
编辑:在 Freepascal 方面:https://bugs.freepascal.org/view.php?id=36706