GCC的构造和析构函数

dlopen打开一个动态链接库时,它会首先调用函数_init做一些初始化的操作,结束时执行_finit进行收尾操作。但是我们编写动态链接库时候不能覆盖_init和_finit,不过可以利用GCC指定构造函数和析构函数函数来完成,示例代码:

#include <stdio.h>

__attribute ((constructor)) void init(void)

{

  printf("%s\n", __func__);

}

__attribute ((destructor)) void fini(void)

{

  printf("%s\n", __func__);

}

int main(void) {
  printf("main\n");
  return 0;
}

执行:

[lu4nx@localhost tmp]$ ./a.out
init
main
fini

GCC4.7以前的版本,编译时会将构造函数和析构函数放在.ctor段和.dtor段中,分别由__do_global_ctors_aux和__do_global_dtors_aux去执行:

[lu4nx@localhost tmp]$ objdump -s -j .ctors a.out

a.out:     file format elf32-i386

Contents of section .ctors:
 8049f00 ffffffff 00000000                    ........
[lu4nx@localhost tmp]$ objdump -s -j .dtors a.out

a.out:     file format elf32-i386

Contents of section .dtors:
 8049f08 ffffffff 00000000                    ........
[lu4nx@localhost tmp]$ nm ./a.out | grep '__[C|D]TOR'
08049f04 d __CTOR_END__
08049f00 d __CTOR_LIST__
08049f0c D __DTOR_END__
08049f08 d __DTOR_LIST__

从GCC4.7开始,.ctor和.dtor段被移除,构造函数和析构函数分别存放到.init_array和.fini_array中了。用4.7的GCC编译后如下:

Contents of section .init_array:
 8049f00 d0830408 fc830408                    ........
Contents of section .fini_array:
 8049f08 b0830408 10840408                    ........

段尾的fc830408和10840408就是构造函数和析构函数的内存地址0x080483fc和0x08048410。