【问题标题】:shm_open is an undefined symbol in shared libraryshm_open 是共享库中的未定义符号
【发布时间】:2021-08-20 06:56:42
【问题描述】:

我编译了一个目标文件shm.o,并将其打包为共享库libshm.so

arm-linux-gnueabihf-gcc -fPIC -o shm.o -c shm.c
arm-linux-gnueabihf-gcc -shared shm.o -o libshm.so -lrt

其中shm.cnm libshm.so 的输出如下所示。

/*shm.c*/

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>

void func_shm(void)
{
    int ret = shm_open("/test_shm", O_CREAT, 0644);
}



/*output of nm*/

00000328 t $a
000002e4 t $a
00000484 t $a
...
...
00000328 t call_weak_fn
0001102c b completed.10740
         w __cxa_finalize@@GLIBC_2.4
...
...
0000034c t deregister_tm_clones
000003e0 t __do_global_dtors_aux
00010f0c t __do_global_dtors_aux_fini_array_entry
00011028 d __dso_handle
00010f10 a _DYNAMIC
00000484 t _fini
00000448 t frame_dummy
00010f08 t __frame_dummy_init_array_entry
00000498 r __FRAME_END__
0000044c T func_shm
00011000 a _GLOBAL_OFFSET_TABLE_
         w __gmon_start__
000002e4 t _init
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
00000390 t register_tm_clones
         U shm_open@@GLIBC_2.4
0001102c d __TMC_END__

正如它所看到的,在倒数第二行,shm_open 是一个未定义的符号,即使附加了-lrt

根据shm_open(3) — Linux manual page;但是nm中显示的glibc版本是2.4。

这些函数在 glibc 2.2 及更高版本中提供。

我的期望是

  1. libshm.so 将定义为 shm_open,因为-lrt被附加在命令的末尾;因此shm_open 不会是未定义的符号。

  2. 任何调用func_shm的应用程序只需要链接到 libshm.so 未指定 -lrt

应该怎么做才能解决这个问题?

【问题讨论】:

  • 尝试使用 -lpthread 和 -lrt。
  • 试过了。不管是arm-linux-gnueabihf-gcc -shared shm.o -o libshm.so -lrt -lpthread还是arm-linux-gnueabihf-gcc -shared shm.o -o libshm.so -lpthread -lrt,还是未定义的符号。
  • 您可以尝试发布原始错误消息。我仍然不确定这是您遇到的链接时问题,还是运行时问题 - 即 dlopen()。

标签: linux linker shared-libraries shared-memory glibc


【解决方案1】:

正如它所看到的,在倒数第二行,shm_open 是一个未定义的符号,即使附加了 -lrt。

这是预期的:您正在链接librt.soshm_open定义librt.so 中,不在在您的库中。

我的期望是在链接过程之后,libshm.so 会有一个 shm_open 的定义,所以 shm_open 不应该是一个未定义的符号。

这种期望是错误的。

您所描述的是如果您与librt.a(存档库)链接会发生什么。在这种情况下,链接器会将实现shm_open() 的对象拉入libshm.so

但是由于您是针对librt.so(它提供了定义)进行链接,因此链接器仅记录librt.so 在运行时是必需的,而shm_open() 在运行时将需要来自某个外部共享库。 libshm.so 中对 shm_open() 的引用仍未解决。

另外,任何调用func_shm的应用程序只需要链接到libshm.so而不需要指定-lrt

确实应该已经发生了(前提是您将libshm.so-lrt 链接起来,就像您的命令行显示的那样)。

如果应用程序本身没有从librt.so 调用任何东西,而只调用func_shm(),那么将它与gcc main.o -L/... -lshm 链接应该可以工作。

我在 Linux/x86_64 上试过这个,它成功了:

gcc -fPIC -shared -o libshm.so shm.c -lrt

# Verify that libshm.so requires librt.so:
readelf -d libshm.so | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]

gcc main.c -L. -lshm
# success

现在,您可能会感到困惑,因为上面链接的应用程序实际上不会运行:

./a.out
./a.out: error while loading shared libraries: libshm.so: cannot open shared object file: No such file or directory

但这是一个完全不同的问题——应用程序不知道要找到哪个目录libshm.so。要解决此问题,请添加 -Wl,-rpath=/path/to/dir/path/to/dir 是运行时要在其中找到 libshm.so 的目录)。

【讨论】:

  • 我编辑了问题,使其与原始问题略有不同。您能否在此答案中添加更具体的内容以使其完美?
猜你喜欢
  • 2016-10-16
  • 2011-02-28
  • 2018-04-14
  • 1970-01-01
  • 2011-07-19
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多