共享库构造和析构函数

共享库构造和析构函数

Content #

GCC提供了一种共享库的构造函数,只要在函数声明时加上“_attribute_((constructor))”的属性,即指定该函数为共享库构造函数,拥有这种属性的函数会在共享库加载时被执行,即在程序的main函数之前执行。如果我们使用dlopen()打开共享库,共享库构造函数会在dlopen()返回之前被执行。

与共享库构造函数相对应的是析构函数,可以使用在函数声明时加上“_attribute_((destructor))”的属性,这种函数会在main()函数执行完毕之后执行(或者是程序调用exit()时执行)。如果共享库是运行时加载的,那么使用dlclose()来卸载共享库时,析构函数将会在dlclose()返回之前执行。声明构造和析构函数的格式如下:

void __attribute__((constructor)) init_function(void);
void __attribute__((destructor))  fini_function (void);

如果我们使用了这种析构或构造函数,那么必须使用系统默认的标准运行库和启动文件,即不可以使用GCC的“-nostartfiles”或“-nostdlib”这两个参数。因为这些构造和析构函数是在系统默认的标准运行库或启动文件里面被运行的,如果没有这些辅助结构,它们可能不会被运行。

如果我们有多个构造函数,那么默认情况下,它们被执行的顺序是没有规定的。如果我们希望构造和析构函数能够按照一定的顺序执行,GCC为我们提供了一个参数叫做优先级,我们可以指定某个构造或析构函数的优先级:

void __attribute__((constructor(5))) init_function1(void);
void __attribute__((constructor(10))) init_function2(void);

对于构造函数来说,属性中优先级数字越小的函数将会在优先级大的函数之前运行;而对于析构函数来讲,则刚好相反。这种安排有利于构造函数和析构函数能够匹配,比如某一对构造函数和析构函数分别用来申请和释放某个资源,那么它们可以拥有一样的优先级。这样做的结果往往是先申请的资源后释放,符合资源释放的一般规则。

From #

程序员的自我修养