gpt4 book ai didi

c++ - 是首先调用 init 部分函数还是构造函数?

转载 作者:行者123 更新时间:2023-11-28 01:32:16 26 4
gpt4 key购买 nike

考虑以下代码:

#include <iostream>
#include <stdio.h>

void preinit_void();
void init_void();

__attribute__((section(".init_array")))
void (*p_init)(void) = &init_void;

void constructor_void() __attribute__((constructor));
void constructor_void() {
printf(__FUNCTION__);
}

__attribute__((section(".preinit_array")))
void (*p_preinit)(void) = &preinit_void;


void preinit_void() {
printf(__FUNCTION__);
}

void init_void() {
printf(__FUNCTION__);
}

int main() {
std::cout << __FUNCTION__ << '\n';
}

运行代码时的输出是

preinit_voidinit_voidconstructor_voidmain

如果我将代码更改为:

#include <iostream>
#include <stdio.h>

void preinit_void();
void init_void();

void constructor_void() __attribute__((constructor));
void constructor_void() {
printf(__FUNCTION__);
}

__attribute__((section(".init_array")))
void (*p_init)(void) = &init_void;

__attribute__((section(".preinit_array")))
void (*p_preinit)(void) = &preinit_void;


void preinit_void() {
printf(__FUNCTION__);
}

void init_void() {
printf(__FUNCTION__);
}

int main() {
std::cout << __FUNCTION__ << '\n';
}

输出变为:

preinit_voidconstructor_voidinit_voidmain

我对哪个部分先初始化感到困惑。输出的变化仅仅是因为编译器的解析(它首先找到了 .init_array 部分而不是 constructor)还是有一个合适的初始化顺序?

最佳答案

在当前 (GNU) 系统上,对 ELF 构造函数的引用被放入 .init_array 部分,就像您手动添加的条目一样。这就是为什么当您更改源代码顺序时执行顺序会改变的原因。 GCC 和 binutils 具有基于优先级使用单独部分的语言扩展,链接编辑器会将所有内容序列化为每个应用程序/共享对象的最终 .init_array 部分(基于源代码和链接顺序,按优先级排序后)。

根据对象之间的依赖关系(通过DT_NEEDED 标记表示)进行拓扑排序后,执行不同共享对象的构造函数数组,以便对象在其依赖关系之后被初始化。

这远远超出了 C++ 对初始化的要求,但在各种 (GNU) ABI 相关文档中或多或少地指定了它,并且不会更改。由于引入了新功能(例如,多个 DF_1_INITFIRST 对象,尽管这有点令人费解),某些方面可能会发生变化,但它们希望只会影响实际使用这些功能的进程。

关于c++ - 是首先调用 init 部分函数还是构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51000066/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com