什么时候gcc __attribute __((构造函数))运行?

che*_*che 7 c gcc posix shared-libraries dlopen

假设我有一个带有GCC构造函数的libA.so.

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

依赖关系看起来像这样:

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

现在,当我运行程序时:

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

显然,当它们被加载到内存中时,dlopen会执行库的构造函数.这是在某处指定的,链接器如何检查哪些库已经加载?

(为什么我要问:在一个场合,我在一些未完全理解的情况下得到了一个两次执行的构造函数.我是否正确地假设这完全被破坏并且在正常情况下不应该发生?)

nin*_*alj 6

对于ELF文件,__attribute__((constructor))标记的函数最终从DT_INIT(初始化函数)标记运行.同样适用于__attribute((destructor))DT_FINI(终止功能)标签.

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

终止函数atexit()在用户atexit()处理程序之后从处理程序运行.终止功能以其相应的初始化功能的相反顺序运行.

ELF标准注意到以下内容:

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

如果你没有看到,那就是一个bug.