共享库构造函数不起作用 [英] shared library constructor not working

查看:80
本文介绍了共享库构造函数不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的共享库中,我必须在加载时进行一定的初始化。如果我使用GCC属性 __ attribute__((构造函数))定义函数,它不起作用,即当链接我的共享库的程序加载时它不会被调用。

如果我将函数名称更改为 _init(),它就可以工作。显然, _init() _fini()函数的用法是不建议使用



不知道为什么 __ attribute__((构造函数))不起作用?这是与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 \\\
,smlib_count);
}

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

int smlib_count_get(){
return smlib_count;
}

为了构建.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

由于.so不是在其中一个标准位置,我更新了 LD_LIBRARY_PATH ,并将另一个程序中的.so链接起来。构造函数不会被调用。如果我将它更改为 _init(),它就可以工作。

解决方案

好吧,我已经看了这个,看起来好像是你的中间 gcc 步骤(使用 -c )导致了这个问题。这是我对我所看到的内容的解释。



当您使用<$ c $编译为 .o c> setup(), gcc 只是将它视为一个普通函数(因为您不是编译为)。所以,所以它不关心)。然后, ld 没有看到任何 _init()或类似于 DT_INIT code>在ELF的动态部分中,假设没有构造函数。

当您编译为 .o _init() gcc 也将它视为正常函数。实际上,它看起来像目标文件是相同的,除了函数名称本身!因此,再次, ld 查看 .o 文件,但是这次看到 _init ()函数,它知道它正在查找,并决定它是一个构造函数,并相应地在新的<$ c $中创建 DT_INIT 条目c> .so



最后,如果您一步完成编译和链接,就像这样:

  gcc -Wall -shared -fPIC -o libsmlib.so smlib.c 

然后发生什么是 gcc 看到并理解了 __属性_((构造函数))创建一个共享对象,并相应地创建一个 DT_INIT 条目。



短版本:使用 gcc 来编译并链接到一个步骤。如果需要,您可以使用 -Wl (请参见手册页)传入其他选项,如 -soname code> -Wl,-soname,libsmlib.so.1 。


In my shared library I have to do certain initialization at the load time. If I define the function with the GCC attribute __attribute__ ((constructor)) it doesn't work, i.e. it doesn't get called when the program linking my shared library is loaded.

If I change the function name to _init(), it works. Apparently the usage of _init() and _fini() functions are not recommended now.

Any idea why __attribute__ ((constructor)) wouldn't work? This is with Linux 2.6.9, gcc version 3.4.6

Edit:

For example, let's say the library code is this the following:

#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;
}

For building the .so I do the following:

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

Since the .so is not in one of the standard locations I update the LD_LIBRARY_PATH and link the .so from a another program. The constructor doesn't get called. If I change it to _init(), it works.

解决方案

Okay, so I've taken a look at this, and it looks like what's happening is that your intermediate gcc step (using -c) is causing the issue. Here's my interpretation of what I'm seeing.

When you compile as a .o with setup(), gcc just treats it as a normal function (since you're not compiling as a .so, so it doesn't care). Then, ld doesn't see any _init() or anything like a DT_INIT in the ELF's dynamic section, and assumes there's no constructors.

When you compile as a .o with _init(), gcc also treats it as a normal function. In fact, it looks to me like the object files are identical except for the names of the functions themselves! So once again, ld looks at the .o file, but this time sees a _init() function, which it knows it's looking for, and decides it's a constructor, and correspondingly creates a DT_INIT entry in the new .so.

Finally, if you do the compilation and linking in one step, like this:

gcc -Wall -shared -fPIC -o libsmlib.so smlib.c

Then what happens is that gcc sees and understands the __attribute__ ((constructor)) in the context of creating a shared object, and creates a DT_INIT entry accordingly.

Short version: use gcc to compile and link in one step. You can use -Wl (see the man page) for passing in extra options like -soname if required, like -Wl,-soname,libsmlib.so.1.

这篇关于共享库构造函数不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆