函数属性__attribute__((constructor))和__attribute__((destructor))

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.

展开阅读全文
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值