我正在尝试将一个驱动使用ftdi2332h芯片的应用程序从Windows移植到Linux。我按照这些说明在Ubuntu 10.04系统上安装了libftd2xx库。
当我尝试编译任何样例程序时,会出现以下错误:
/usr/local/lib/libftd2xx.so: undefined reference to `memcpy@GLIBC_2.14'
collect2: ld returned 1 exit status
有关如何修复这个问题的任何指南吗?
我正在尝试将一个驱动使用ftdi2332h芯片的应用程序从Windows移植到Linux。我按照这些说明在Ubuntu 10.04系统上安装了libftd2xx库。
当我尝试编译任何样例程序时,会出现以下错误:
/usr/local/lib/libftd2xx.so: undefined reference to `memcpy@GLIBC_2.14'
collect2: ld returned 1 exit status
有关如何修复这个问题的任何指南吗?
mempcy@GLIBC_2.14
被称为版本化符号。Glibc在使用它们,而其他运行时库(如musl do not)则不使用。
mempcy@GLIBC_2.14
在Linux上编译的重要性是由于Glibc在2012年改变了memcpy
的工作方式。 memcpy
曾经将字节从{begin → end}(低内存地址到高内存地址)复制。 Glibc 2.13提供了一个优化的memcpy
,在某些平台上将{end → begin}复制。我相信“某些平台”包括具有SSE4.1的英特尔机器。然后,Glibc 2.14提供了一个memcpy
,恢复了{begin → end}的行为。
一些程序依赖于{begin → end}复制。当程序使用重叠缓冲区时,memcpy
会产生未定义的行为。在这种情况下,程序应该使用memmove
,但由于发生了{begin → end}的复制,它们得以继续运行。还请参见Strange sound on mp3 flash website(由Adobe Flash引起),Glibc change exposing bugs(在LWN上),The memcpy vs memmove saga等。
为了解决这个问题,看起来你可以将以下内容添加到你的源代码中:
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
$ cat version.c
__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
libftd2xx.so
)链接到了一个比您链接的更新的glibc版本,这是合理的,考虑到前面的事实。libftd2xx.so
以针对您系统的glibc版本(可能不是一个选项,因为它只是二进制文件),要么更新您的操作系统。Ubuntu 10.04相当老旧。/opt
的地方。您可以下载并编译libc,并安装在/opt/lib/libcX/libc.so.6
下。然后,您可以拥有一个脚本:
LD_LIBRARY_PATH=/opt/lib/libcX:/lib/:/usr/lib:/usr/share/lib
./your_program
我不确定,但如果你正在使用交叉编译器,你必须在某个地方安装兼容版本的基本库(不是在/usr/include
和/usr/lib
),并确保编译器使用它们,而不是本地编译器的库。同时,你必须确保整个工具链版本兼容。(我知道这不是一个非常完整的答案,但这就是我所知道的。)
我无法让汇编symver技巧起作用,所以我采取了更激烈的行动,重新定义了memcpy:
extern "C" void *memcpy(void *dest, const void *src, size_t n)
{
return memmove(dest, src, n);
}
这显然是一种更冒险的选择,可能会产生重复定义的问题。它还会在每次调用memcpy时添加一个额外的跳转,而memmove可能会稍微慢一些。但也许它可以帮助您在旧版本的Linux上启动某些东西。
升级到Ubuntu 12.04。我使用Qt
时遇到了同样的问题,原来是glibc库太旧了。在互联网上搜索后得知,尝试自行升级glibc非常危险。
memcpy
,但是在阅读了这篇文章之后,我认为这种方法可能会导致实际调用旧的memcpy
的代码崩溃。 - Accountant مLD_PRELOAD
确保memcpy
绑定到Glibc 2.2.5。 - jwwobjdump -T ./fooProgram
检查它是否实际上更改了版本标签。 - Accountant م