考虑以下代码:
#include <stdio.h>
void __attribute__ ((constructor)) a_constructor()
{
printf("%s\n", __func__);
}
void __attribute__ ((constructor)) b_constructor()
{
printf("%s\n", __func__);
}
int main()
{
printf("%s\n",__func__);
}
我将以上代码编译为:
gcc -ggdb prog2.c -o prog2
。该代码按预期运行。a_constructor
b_constructor
main
但是当我使用
objdump -d prog2 > f
看到它的转储时。在__do_global_ctors_aux
或其他任何地方都没有对_init
的调用,也没有__do_global_ctors_aux
的定义。那么,如何调用构造函数? __do_global_ctors_aux
的定义在哪里?这是一些优化吗?我也尝试过在没有优化的情况下编译它:
gcc -ggdb -O0 prog2.c -o prog2
。请说清楚。编译是在32位linux机器上完成的。
编辑
我从gdb bt的输出是:
Breakpoint 1, a_constructor () at prog2.c:5
5 printf("%s\n", __func__);
(gdb) bt
#0 a_constructor () at prog2.c:5
#1 0x080484b2 in __libc_csu_init ()
#2 0xb7e31a1a in __libc_start_main (main=0x8048445 <main>, argc=1, argv=0xbffff014, init=0x8048460 <__libc_csu_init>,
fini=0x80484d0 <__libc_csu_fini>, rtld_fini=0xb7fed180 <_dl_fini>, stack_end=0xbffff00c) at libc-start.c:246
#3 0x08048341 in _start ()
最佳答案
那么,如何调用构造函数?
如果查看使用gcc -g -O0 -S -fverbose-asm prog2.c -o prog2.s
产生的反汇编,则有以下内容:
.text
.Ltext0:
.globl a_constructor
.type a_constructor, @function
a_constructor:
.LFB0:
.file 1 "test.c"
.loc 1 4 0
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
.loc 1 5 0
movl $__func__.2199, %edi #,
call puts #
.loc 1 6 0
popq %rbp #
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size a_constructor, .-a_constructor
.section .init_array,"aw"
.align 8
.quad a_constructor
在上面,函数
a_constructor
放在.text
部分中。并且指向该函数的指针也附加到.init_array
部分。在调用main
之前,glibc遍历此数组并调用在那里找到的所有构造函数。