何时gcc __attribute __((构造函数))运行? [英] When exactly is gcc __attribute__((constructor)) run?

查看:245
本文介绍了何时gcc __attribute __((构造函数))运行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我的程序程序依赖于libA.so,所以当我运行它时,libA.so被打开并且它的构造函数被执行。现在,我也有一个模块libC.so,它也依赖于libA。我运行加载libC的 dlopen(libC.so),并根据我的实验执行libA的构造函数



依赖关系如下所示:


  • libA具有构造函数
  • libB还有一个构造函数
  • libC依赖于libA和libB
  • 程序依赖于libA
  • 程序链接libC通过dlopen()



现在,当我运行程序时:


  • libA的构造函数在main()启动之前运行

  • libB的构造函数由dlopen()运行
>

显然,dlopen在加载到内存中时执行库的构造函数。这是指定的地方,以及如何链接器检查哪些库已经加载?

(为什么我问:在一个场合,我有一个构造函数执行两次情况下,在一些不完全理解的条件下,我是否正确地认为这是完全破碎的,并且在正常情况下不应该发生?)

对于ELF文件, __属性__((构造函数))标记函数最终从 DT_INIT 功能)标签。同样也适用于 __属性((析构函数)) DT_FINI (终止函数)标记。



初始化函数在执行重定位后运行,并且在将控制返回给程序之前运行,程序加载时共享对象意味着在将控制权转交给 main(),并且运行时加载的共享对象可能会被解释为在从 dlopen()返回之前。初始化函数 DT_NEEDED 共享对象在当前共享对象的初始化函数之前运行。



终止函数运行从 atexit()处理程序,在用户 atexit()处理程序之后。终止函数按照与其相应的初始化函数相反的顺序运行。



ELF标准注释如下:

动态链接器确保它不会
不止一次地执行任何初始化或终止函数。

如果你看到其他的东西,那就是一个bug。 p>

Let's say I have an libA.so with GCC constructor.

My program "program" depends on libA.so, so when I run it, libA.so gets opened and its constructor is executed. Now, I also have a module, libC.so, which also depends on libA. I run dlopen("libC.so"), which loads libC, and according to my experiments, also executes libA's constructor.

Dependencies look like this:

  • libA has the constructor
  • libB also has a constructor
  • libC depends on libA and libB
  • program depends on libA
  • program links libC via dlopen()

Now, when I run the program:

  • libA's constructor gets run before main() starts
  • libB's constructor gets run by dlopen()

Apparently, dlopen executes constructors of libraries when they are loaded into memory. Is this specified somewhere, and how does the linker check which libs are already loaded?

(Why I'm asking: On an occassion, I got a constructor executed twice in situation under some not-fully-understood conditions. Am I right in presuming that this was totally broken and should never happen under normal situation?)

解决方案

For ELF files, __attribute__((constructor)) marked functions are ultimately run from the DT_INIT (initialization function) tag. Likewise for __attribute((destructor)) and the DT_FINI (termination function) tag.

Initialization functions are run after relocations are performed, and before returning control to the program, which for program-load-time loaded shared objects means before tranfering control to main(), and for runtime loaded shared objects could probably be interpreted as before returning from dlopen(). Initialization functions from DT_NEEDED shared objects are run before the initialization function in the current shared object.

Termination functions are run from atexit() handlers, after user atexit() handlers. Termination functions are run in reverse order of their corresponding initialization functions.

The ELF standard notes the following:

The dynamic linker ensures that it will not execute any initialization or termination functions more than once.

If you are seeing otherwise, then it's a bug.

这篇关于何时gcc __attribute __((构造函数))运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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