不明白这件事:我在 c 中有一个程序,并且我正在将一些第二方静态库链接到该程序(据我所知,lhis 库也可以是 dll 上的一些包装器)-它是否可以将我的程序“隐式地” (我的意思是在我的代码中没有明确调用它)从那些库中运行一些初始化代码(这将在我的 main() 例程之前执行? - 或者它不能?)
我在这里询问关于 c 代码的问题(最终关于没有任何 c++ 功能但由 c++ 编译器以 c++ 模式编译的 c 代码 - 链接的静态库可以用任何语言编写)
tnx 回答
不明白这件事:我在 c 中有一个程序,并且我正在将一些第二方静态库链接到该程序(据我所知,lhis 库也可以是 dll 上的一些包装器)-它是否可以将我的程序“隐式地” (我的意思是在我的代码中没有明确调用它)从那些库中运行一些初始化代码(这将在我的 main() 例程之前执行? - 或者它不能?)
我在这里询问关于 c 代码的问题(最终关于没有任何 c++ 功能但由 c++ 编译器以 c++ 模式编译的 c 代码 - 链接的静态库可以用任何语言编写)
tnx 回答
如果没有从 c 或 c++ 中的代码显式调用,任何类型的链接库都无法运行初始化代码。
这取决于您的平台。
如果您使用 GCC,您可以使用__attribute__((constructor))
. 此函数将在您的主函数之前调用,甚至从动态库中调用。
__attribute__((constructor))
void my_init()
{
/* do stuff; */
}
您可以在GCC 文档和这个 SO question中找到更多详细信息
在 VC 中也有一些方法可以做到这一点,尽管不是那么简单。(见这个问题)
编辑:如果你链接到一些第三方库,它可能会调用一些初始化函数。即使库是用 C 语言编写的。而且没有可移植和通用的方法,如何检测它。而且您可能不想弄乱它,因为库可能依赖于它在 main 启动之前被调用。
如果你真的想知道它是否调用了某些东西,你必须查看二进制文件。在 ELF 文件中,有一个部分.init_array
包含指向将在启动时调用的函数的“指针”,并且可以使用 objdump ( objdump -s -j .init_array <binary>
)转储它
我认为 Windows 中的 PE 文件中有类似的部分,但我从未使用过这些部分,抱歉。
EDIT2:该main()
函数启动您的代码。但在执行之前还有一些事情要做。当您编译程序时,编译器会添加一些在程序之前执行的代码main()
并初始化程序环境(堆栈、C 库......)。
在 Linux 下,这将主要由函数_start
和_init
. 作为一项功能,您可以指示编译器在函数内部也调用一些您的_init
函数。
动态库不具备该_start
功能,但在加载库时仍然_init
会调用该功能。并且其中也可以包含对某些用户函数的调用。
在静态库的情况下,它变得有点复杂,因为链接器可能会删除一些函数,而这些函数从未从你的程序中调用过。但是一旦它被调用(甚至间接地从库代码中调用)或者只是在库中的某个地方被引用并且从未真正调用过,它最终会在你的二进制文件中并且会被调用 before main()
。
一些关于_start
和的信息_init
可以在这里找到。
在 windows 下,编译器和链接器是不同的,但应该以类似的方式工作。