1)函数属性功能
__attribute__ ((constructor))会使函数在main()函数之前被执行
__attribute__ ((destructor))会使函数在main()退出后执行
2)功能范围
函数属性__attribute__((constructor))和__attribute__((destructor))在可执行文件或者库文件里都可以生效
3)与全局变量比较
全局变量对象的构造函数和析构函数分别在__attribute__((constructor))和__attribute__((destructor))标志的函数之前调用。
1、可执行文件的函数调用
例子如下:
#include <iostream>
//函数属性声明
void beforemain() __attribute__((constructor));
void aftermain() __attribute__((destructor));
void breforemain()
{
std::cout << "before main function" << std::endl;
}
void aftermain()
{
std::cout << "after main function" << std::endl;
}
class AAA{
public:
AAA(){std::cout << "global veriable constructor" << std::endl;}
~AAA(){std::cout << "global veriable destructor" << std::endl;}
};
AAA aaa;//全局变量
int main(int argc,char** argv)
{
std::cout << "in main function" << std::endl;
return 0;
}
输出结果:global veriable constructor
before main function
in main function
global veriable destructor
after main function
__attribute__((constructor))标志的函数和全局变量对象(或静态变量)的构造函数在main函数之前调用。
__attribute__((destructor))标志的函数和全局变量对象(或静态变量)的析构函数在main函数之后调用。
全局变量对象的构造函数和析构函数的调用在__attribute__标志的函数之前。
但是如果要在main()之前或者是执行完成之后,需要执行很多的前处理动作或者是后处理动作,我们应该怎么处理?
也许,你需要下面这些东西:
__attribute__((constructor(PRIORITY)))
__attribute__((destructor(PRIORITY)))
|
PRIORITY: 优先级.
好吧,下面就来试试:
执行的输出如下:
从输出的信息看,前处理都是按照优先级先后执行的,而后处理则是相反的。
2、库文件的函数调用
库文件:
#include <stdio.h>
__attribute__ ((constructor)) static void ktest_init(void);
__attribute__ ((destructor)) static void ktest_deinit(void);
void ktest_init(void)
{
printf("call ktest init./n");
}
void ktest_deinit(void)
{
printf("call ktest deinit./n");
}
void test1()
{
printf("call test1./n");
}
void test2()
{
printf("call test2./n");
}
void test3()
{
printf("call test3./n");
}
编译库文件gcc -fPIC -c ktest.c
产生连接文件ktest.ogcc -shared -o libktest.so ktest.o
产生库文件libktes.so
调用库文件的主函数
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h> /* dlopen, dlsym, dlclose */
int main(int argc, char **argv)
{
test1();
test2();
test3();
/* below only for testing dynamic linking loader */
void *handle;
void (*test)();
char *error;
handle = dlopen ("/path_to_lib/libktest.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
test = dlsym(handle, "test2");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
(*test)();
dlclose(handle);
return 0;
}
编译可执行文件calllib
gcc calllib.c -o calllib -ldl -L./ -lktest
调用可执行文件
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH && ./calllib
输出结果如下:
call ktest init.
call test1.
call test2.
call test3.
call test2.
call ktest deinit.