【问题标题】:can static linking result in executing some init routines?静态链接会导致执行一些初始化程序吗?
【发布时间】:2013-08-14 14:47:21
【问题描述】:

不明白这个东西:我有一个c程序 我正在将一些第二方静态库链接到那个 (据我所知,他的库也可以是一些包装器 dlls) - 它可以让我的程序“隐式”(我的意思是 没有在我的代码中明确调用)运行一些 这些库中的初始化代码(这将 在我的 main() 例程之前执行? - 或者它不能?)

我在这里询问有关 c 代码的问题(最终有关 c 没有任何 c++ 特性但以 c++ 模式编译的代码 通过 c++ 编译器 - 链接的静态库可以写成 任何语言)

tnx 回答

【问题讨论】:

  • 你在什么平台上?
  • windows,我最终也使用了很多编译器 gcc、vc、icc、mingw 等

标签: c++ c linker shared-libraries static-libraries


【解决方案1】:

这取决于您的平台。

如果您使用 GCC,您可以使用 __attribute__((constructor)) 声明函数。这个函数在你的 main 之前被调用,即使是从动态库中。

__attribute__((constructor))
void my_init()
{
    /* do stuff; */
}

您可以在GCC documentationthis SO question 中找到更多详细信息

在 VC 中也有一些方法可以做到这一点,尽管不是那么简单。 (见SO question

编辑:如果你链接到一些第三方库,它可能会调用一些初始化函数。即使库是用 C 语言编写的。而且没有可移植和通用的方法,如何检测它。而且您可能不想弄乱它,因为库可能依赖于它在 main 启动之前被调用。

如果你真的想知道它是否调用了某些东西,你必须查看二进制文件的内部。 在 ELF 文件中,有一个部分 .init_array 包含指向将在启动时调用的函数的“指针”,并且可以使用 objdump (objdump -s -j .init_array <binary>) 转储它

我认为 Windows 中的 PE 文件中有类似的部分,但我从未使用过这些部分,抱歉。

EDIT2main() 函数启动您的代码。但在执行之前还有一些事情要做。当您编译您的程序时,编译器会添加一些在main() 之前执行的代码并初始化程序环境(堆栈、C 库...)。

在 Linux 下,这将主要由函数 _start_init 提供。作为一项功能,您可以指示编译器在 _init 函数内调用您的一些函数。

动态库没有_start 函数,但仍有_init 将在库加载时调用。并且其中也可以包含对某些用户函数的调用。

在静态库的情况下,它变得有点复杂,因为链接器可能会删除一些函数,而这些函数从未从您的程序中调用。但是一旦它被调用(甚至间接地从库代码中调用)或者只是在库中的某个地方被引用并且从未真正调用过,它最终会在你的二进制文件中并且会在 main() 之前被调用。

关于_start_init 的一些信息可以是found here

在windows下编译器和链接器是不同的,但应该以类似的方式工作。

【讨论】:

  • 我是从使用外部库的主程序编码器的角度询问 - 所以我可以确定链接的库初始化没有被调用,或者我可以怀疑它们是 - 有没有办法检查它?跨度>
  • 如果实现是符合标准的 C++ 实现,则程序中使用的所有对象(包括库文件中的对象)的构造函数必须在 main 启动之前调用。我可以想象 Windows 在这里像在大多数其他地方一样存在一致性错误,但是如果您使用 gcc 或 icc 而不是 MSVC,我真的怀疑他们会遇到这么重要的错误。
  • 我正在谈论更多关于 c 程序(但在 c++ 模式下编译)并链接许多类似 c 的小型库 - 那是什么?他们会调用 inits 吗? - 我不明白你的答案:C
  • 查看编辑后的答案。 TL;DR:初始化代码可能会被调用,甚至在你的 main() 之前。
  • 遗憾的是,我不完全理解它是如何工作的以及为什么即使在 c 中也调用它
【解决方案2】:

任何类型的链接库都无法运行初始化代码,除非您的代码在 c 或 c++ 中进行显式调用。

【讨论】:

  • 这不是一般的情况。
  • 如果它有全局变量可能。但是没有人会使用全局变量,对吧?
  • 你在上面,可能是在谈论与 c++ 库链接的 c++,与 c 库链接的 c 程序,与 c++ 库链接的 c 程序,这是否也涉及触发隐式初始化?
  • 我也在询问以 c++ 模式编译的 c 代码,因为这是我真正使用的
  • 您不应该使用 C++ 编译器来编译 C,因为这两种语言之间存在细微差别的各种结构。你的编译器没有 C 模式吗?
猜你喜欢
  • 1970-01-01
  • 2011-11-11
  • 2016-02-21
  • 2016-04-21
  • 2015-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多