共享库构造函数不工作

Man*_*har 10 c linux gcc shared-libraries

在我的共享库中,我必须在加载时进行某些初始化.如果我使用GCC属性定义函数__attribute__ ((constructor))它不起作用,即在加载链接我的共享库的程序时不会调用它.

如果我将函数名称更改为_init(),它可以工作.显然现在不推荐使用_init()_fini()功能.

知道为什么__attribute__ ((constructor)) 不行吗?这是Linux 2.6.9,gcc版本3.4.6

编辑:

例如,假设库代码如下:

#include <stdio.h>

int smlib_count;

void __attribute__ ((constructor)) setup(void) {
    smlib_count = 100;
    printf("smlib_count starting at %d\n", smlib_count);
}

void smlib_count_incr() {
    smlib_count++;
    smlib_count++;
}

int smlib_count_get() {
    return smlib_count;
}
Run Code Online (Sandbox Code Playgroud)

为了构建.so,我执行以下操作:

gcc -fPIC -c smlib.c
ld -shared -soname libsmlib.so.1 -o libsmlib.so.1.0 -lc smlib.o
ldconfig -v -n .
ln -sf libsmlib.so.1 libsmlib.so
Run Code Online (Sandbox Code Playgroud)

由于.so不在标准位置之一,我更新LD_LIBRARY_PATH并链接.so来自另一个程序.构造函数不会被调用.如果我将其更改为_init(),则可行.

Dan*_*ego 4

好的,我已经查看了这一点,看起来发生的情况是您的中间gcc步骤(使用-c)导致了问题。这是我对所看到内容的解释。

当您编译为.owith时setup()gcc只需将其视为普通函数(因为您没有编译为 a .so,所以它不在乎)。然后,在 ELF 的动态部分ld中看不到任何_init()或类似 a 的内容DT_INIT,并假设没有构造函数。

当您编译为.owith时_init()gcc也将其视为普通函数。事实上,在我看来,除了函数本身的名称之外,目标文件是相同的!因此,再次ld查看该.o文件,但这一次看到一个_init()函数,它知道它正在寻找该函数,并确定它是一个构造函数,并相应地DT_INIT在 new 中创建一个条目.so

最后,如果您一步完成编译和链接,如下所示:

gcc -Wall -shared -fPIC -o libsmlib.so smlib.c
Run Code Online (Sandbox Code Playgroud)

然后发生的事情是在创建共享对象的上下文中gcc看到并理解,并相应地创建一个条目。__attribute__ ((constructor))DT_INIT

简短版本:用于gcc一步编译和链接。您可以使用-Wl(请参阅手册页)传递额外选项,例如-soname如果需要的话,例如-Wl,-soname,libsmlib.so.1.

  • 它不必一步到位。使它起作用的是使用 gcc 和 -shared 来链接,而不是 ld。 (6认同)