有人可以解释一下以下代码是如何工作的吗?
# if defined(__ELF__)
# define __SECTION_FLAGS ", \"aw\" , @progbits"
/* writable flag needed for ld ".[cd]tors" sections bug workaround) */
# elif defined(__COFF__)
# define __SECTION_FLAGS ", \"dr\""
/* untested, may be writable flag needed */
# endif
asm
(
".section .ctors" __SECTION_FLAGS "\n"
".globl __ctors_begin__\n"
"__ctors_begin__:\n"
".previous\n"
);
asm /* ld ".[cd]tors" sections bug workaround */
(
".section .ctors0" __SECTION_FLAGS "\n"
".globl __ctors0_begin__\n"
"__ctors0_begin__:\n"
".previous\n"
);
同样地,我们得到__ctors_end__
,__ctors0_end__
,并且也以这种方式获得析构函数位置。在一些ld bug变通方法之后,执行从__ctors_begin__
到__ctors_end__
的指针所指向的所有函数。我不知道汇编程序,这段代码对我来说无法解释。
BTW:我知道从C调用C ++构造函数/析构函数不是一个安全或容易的任务。
答案 0 :(得分:5)
这实际上不是CPU执行的代码,而是添加到目标文件的元数据中。它告诉链接器在存储构造函数的最终可执行文件的同一部分(=部分)中创建一些全局变量(上例中的__ctors_begin__
)(该部分称为.ctors
)。要使其工作,您只需确保首先链接带有“begin”变量的文件,并将带有“end”变量的文件最后链接(但也许您也可以使用__SECTION_FLAGS
来控制它)。这为你提供了你正在寻找的记忆范围。
至于“安全”:嗯,C ++运行时并不神奇。不知何故,它必须知道如何在启动时运行所有构造函数和析构函数,并且不会一直改变。因此,对于编译器的主要版本号,这应该是非常安全的。此外,当它破裂时你很快就会知道: - )