在Linux上使用GCC编译器时,如何使用#pragma init和#pragma fini?

11

我想编写一些代码在共享库加载时调用一些代码。我认为可以这样做:

#pragma init(my_init)

static void my_init () {  
  //do-something
}

int add (int a,int b) {  
  return a+b; 
}

当我使用

gcc -fPIC -g -c -Wall tt.c

编译这段代码时,返回结果为

gcc -fPIC -g -c -Wall tt.c 
tt.c:2: warning: ignoring #pragma init 
tt.c:4: warning: ‘my_init’ defined but not used

所以它忽略了我的 #pragmas。我在真实代码中尝试了这个,因为一个函数没有在 pragma 部分被调用而被忽略,导致我的代码中止。

我该如何让 gcc 使用这些 #pragma init 和 fini 语句?

3个回答

17

编译指示几乎都是特定于编译器的。GCC没有实现init,但您可以使用constructor函数属性来获得相同的效果:

static __attribute__((constructor)) void my_init()
{  
  //do-something
}

还有一个相应的destructor属性。


哦,对于gcc 4.4.6,我在上面的示例中遇到了一个“expected ‘,’ or ‘;’ before ‘{’ token”的错误。当我从函数定义中删除属性,并在其前面放置带有构造函数属性的函数声明时,它按预期/ 文档工作。 - maxschlepzig
@maxschlepzig:在函数定义中,属性需要在声明符之前,已更新。 - caf

3

-3

不要使用C:

// init.cpp
namespace // 一个匿名命名空间
{
     class autoinit
     {
         public:
             ~autoinit(){ /* 如果适用,执行销毁代码 */ }
         private:
             autoinit(){ /* myinit的内容 */ }
             static autoinit _instance;
     };
autoinit autoinit::_instance; // 静态实例强制静态构造 }

如果他要求在任何静态构造函数被调用之前调用他的代码,则这种情况可能无法实现(初始化顺序无法控制且不能保证),在标准C++中几乎不可能实现。 - Grant Peters
@Grant,你能控制使用__attribute__((constructor))声明的函数的相对顺序吗?如果不能,那么它有什么不同呢?此外,这种方法在所有C++实现中都是可移植的,而__attribute__((constructor))语法仅适用于GCC。 - Michael Aaron Safyan
1
我相信__attribute__((constructor))语法确保它在所有其他代码之前被调用。此外,它允许您为该构造函数指定优先级,因此如果指定了多个,则知道运行它们的顺序。至于可移植性,我是说通过标准c++不可能在任何静态类构造函数(即控制初始化)之前调用您的代码,没有可移植的方法可以做到这一点。您只是指出了我已经说过的内容,而您的方法仍然不允许在任何静态类之前运行代码。 - Grant Peters
@Grant Peters - 刚刚偶然发现了这个问题。问题在于静态构造函数也被称为“最先调用的函数”。我曾经处理过相关的问题并进行了快速测试。至少arm-eabi-gcc将C++构造函数调用和使用__attribute__((constructor))定义的函数都放在.init_array部分中。在每个模块的基础上,使用__attribute__((constructor))定义的函数似乎排在前面,但链接输出将它们全部混合在一起。 - sstn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接