共享库构造函数不起作用 [英] shared library constructor not working
问题描述
在我的共享库中,我必须在加载时进行一定的初始化。如果我使用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屋!