即使定义了“-nostdlib”选项,如何运行构造函数

时间:2011-01-21 15:32:46

标签: c gcc shared-libraries

我有一个包含构造函数的动态库。

__attribute__ ((constructor))
void construct() {
    // This is initialization code
}

使用-nostdlib选项编译库,我无法改变它。因此,库中没有.ctor.dtor部分,并且构造函数未在库加载上运行。

正如there所写,应该有一些特殊的措施,即使在这种情况下也允许运行构造函数。您能否告诉我该怎么做以及如何做?

3 个答案:

答案 0 :(得分:0)

为什么需要构造函数?我与之合作的大多数程序员,包括我自己,都拒绝使用带有全局构造函数的库,因为他们经常在输入main时搞乱程序的初始状态。我能想到的一个具体例子是OpenAL,它只是在程序被链接时打破了程序,即使它从未被调用过。我不是那个处理这个bug的项目人员,但是如果我没弄错的话,它与ALSA混淆并打破主程序以后使用ALSA。

如果你的库有非常重要的全局状态,那么看看你是否可以简单地使用全局结构和初始化器。您可能需要添加带有一些指针的标志,以指示它们是指向已分配的内存还是静态内存。另一种方法是将初始化推迟到第一次调用,但除非您使用pthread_once或类似的,否则会出现线程安全问题。

答案 1 :(得分:0)

在某些平台上,生成.init_array/.fini_array个部分以包含所有全局构造函数/析构函数。你可以使用它。

答案 2 :(得分:0)

嗯错过那里没有.ctor和.dtor部分的部分......忘了这个。

#include <stdio.h>
#include <stdint.h>

typedef void (*func)(void);

__attribute__((constructor))
void func1(void) {
     printf("func1\n");
}

__attribute__((constructor))
void func2(void) {
     printf("func2\n");
}

extern func* __init_array_start;

int main(int argc, char **argv)
{
     func *funcarr = (func*)&__init_array_start;
     func f;
     int idx;

     printf("start %p\n", *funcarr);

     // iterate over the array
     for (idx = 0; ; ++idx) {
          f = funcarr[idx];

          // skip the end of array marker (0xFFFFFFFF) on 64 bit it's twice as long ;)
          if (f == (void*)~0)
               continue;

          // till f is NULL which indicates the start of the array
          if (f == NULL)
               break;

          printf("constructor %p\n", *f);
          f();
     }

     return 0;
}

给出了:

Compilation started at Fri Mar  9 09:28:29

make test && ./test
 cc     test.c   -o test
 func2
 func1
 start 0xffffffff
 constructor 0x80483f4
 func1
 constructor 0x8048408
 func2

如果您在Big Endian系统上运行,可能需要交换continue和break,但我不完全确定。

但就像R ..声明在库中使用静态构造函数对于使用您的库的开发人员来说并不是那么好:p