Linux 共享库构造函数不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9472519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
shared library constructor not working
提问by Manohar
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.
在我的共享库中,我必须在加载时进行某些初始化。如果我使用 GCC 属性定义函数,则__attribute__ ((constructor))
它不起作用,即在加载链接我的共享库的程序时不会调用它。
If I change the function name to _init()
, it works. Apparently the usage of _init()
and _fini()
functions are not recommendednow.
如果我将函数名称更改为_init()
,它就可以工作。显然现在不推荐使用_init()
和_fini()
函数。
Any idea why __attribute__ ((constructor))
wouldn't work? This is with Linux 2.6.9, gcc
version 3.4.6
知道为什么__attribute__ ((constructor))
不起作用吗?这是 Linux 2.6.9,gcc
版本 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:
为了构建 .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
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.
由于 .so 不在标准位置之一,我更新LD_LIBRARY_PATH
并从另一个程序链接 .so。构造函数不会被调用。如果我将其更改为_init()
,它会起作用。
采纳答案by Dan Fego
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.
好的,所以我查看了这个,看起来正在发生的事情是您的中间gcc
步骤(使用-c
)导致了问题。这是我对所见所闻的解释。
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.
当您编译为.o
with 时setup()
,gcc
只需将其视为普通函数(因为您没有编译为.so
,所以它不在乎)。然后,在 ELF 的动态部分ld
中看不到任何_init()
类似 aDT_INIT
的内容,并假设没有构造函数。
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 identicalexcept 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
.
当您编译为.o
with 时_init()
,gcc
也将其视为普通函数。事实上,在我看来,除了函数本身的名称之外,目标文件是相同的!所以再次ld
查看.o
文件,但这次看到一个_init()
函数,它知道它正在寻找,并确定它是一个构造函数,并相应地DT_INIT
在 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.
然后发生的事情是在创建共享对象的上下文中gcc
看到并理解__attribute__ ((constructor))
,并相应地创建一个DT_INIT
条目。
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
.
短版:用于gcc
一步编译和链接。您可以使用-Wl
(参见手册页)传递额外的选项,如-soname
需要,如-Wl,-soname,libsmlib.so.1
.
回答by Lunar Mushrooms
From this link:
从这个链接:
"Shared libraries must not be compiled with the gcc arguments -nostartfiles'' or-nostdlib''. If those arguments are used, the constructor/destructor routines will not be executed (unless special measures are taken)."
“不得使用 gcc 参数 -nostartfiles'' 或 -nostdlib'' 编译共享库。如果使用这些参数,则不会执行构造函数/析构函数例程(除非采取特殊措施)。
gcc/ld doesn't set the DT_INIT bit in the elf header when -nostdlib is used . You can check objdump -p and look for the section INIT in both cases. In attribute((constructor)) case you wont find that INIT section . But for __init case you will find INIT section in the shared library.
使用 -nostdlib 时,gcc/ld 不会在 elf 标头中设置 DT_INIT 位。在这两种情况下,您都可以检查 objdump -p 并查找 INIT 部分。在属性((constructor)) 情况下,您不会找到 INIT 部分。但是对于 __init 情况,您会在共享库中找到 INIT 部分。