考虑以下代码:

#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遍历此数组并调用在那里找到的所有构造函数。

08-16 00:00