2021-09-11

关于__attribute__使用的一些心得


attribute(constructor)与__attribute__(destructor)

     在GNU c中,提供了__attribute__,用来给函数以及变量改变属性。这次用到的constructor的作用就是改变函数运行顺序的。


__attribute__((constructor))
void func1() {
    printf("this is func1!\n");
    return;
}

__attribute__((constructor))
void func2() {
    printf("this is func2!\n");
    return;
}

int main() {
    printf("this is main!\n);
}

运行结果:


     可以看出两个定义的函数都在主函数之前运行了,这和平时了解的“主函数是程序的入口。”有些许不同,这主要是为了一些特殊的功能的实现,如注册函数等初始化功能。不仅仅如此GNU还提供了确定这些函数运行优先级的方法,具体代码如下:
__attribute__((constructor(103)))
void func1() {
    printf("this is func1!\n");
    return;
}

__attribute__((constructor(102)))
void func2() {
    printf("this is func2!\n");
    return;
}

int main() {
    printf("this is main!\n);
    return 0;
}

 <font face=微软雅黑">运行结果:

在这里插入图片描述

    由上可以看出两个函数的运行顺序发生了变化,数字小的函数先运行了,这就是函数的执行优先级,优先级从101655350100默认保留,当然这个优先级不仅仅是适用于函数,对于全局变量也是很有用,具体作用后面再说。

对于初始化函数的一些问题以及init_priority()参数的使用

    当我想使用利用初始化函数初始化全局变量时却发生了一些问题,网上找了很久也没找到具体的解决办法。具体问题如下:

class A{
    public:
        string s;
    A(){}
    A(string _s): s(_s){}
};

vector<A> a;

__attribute__((constructor))
void init() {
    a.emplace_back("abc");
    printf("a[0] = %s\n", a[0].s.c_str());
}

int main() {
    a.emplace_back("123");
    printf("a[0] = %s\n", a[0].s.c_str());
    printf("a.size = %ld\n", a.size());
}

运行结果:

在这里插入图片描述


    由上图可以看出在初始化函数中添加的元素在主函数中消失了,这让我百思不得其解,于是上网查找相似的问题,但是收获甚少,只找到一个差不多的帖子,关于C++全局string变量在__attribute__((constructor))函数中赋值的问题,此题主也是在使用设置函数属性时初始化全局变量出现了问题,然后问题下面也有人提到了Devc++没有问题,有人也指出了原因所在,说是全局变量以及函数都是在主函数之前初始化的,但是顺序未知。我在Devc++上测试相 同代码后确实没有产生在g++上出现的问题,随后我就想验证初始化顺序,具体代码如下:

class A{
    public:
        string s;
    A() {
        printf("default structure.\n");
    }

    A(string _s): s(_s) {
        printf("parameter structer.\n");
    }

    void operator=(string _s) {
        this-> = _s;
        printf("operator=\n");
        return ;
    }

    ~A(){
        printf("delete\n");
    }
};

A a;

__attribute__((constructor))
void init() {
    a.emplace_back("abc");
    printf("a = %s\n", a.s.c_str());
}

int main() {
    printf("a = %s\n", a.s.c_str());
    a = "123";
    printf("a = %s\n", a.s.c_str());
    return 0;
}

运行结果:

在这里插入图片描述

    由运行结果可以看出在初始化函数中虽然用到了全局变量a但是该变量却没有初始化(或者说是构造),反而是在初始化完成后才初始化,由此不难看出变量的初始化(或者说是构造)的优先级是在初始化函数后面的,但为什么变量没有初始化却能使用这点我现在还没有弄清楚。问题出在哪已经明白了,接下来便是找解决办法了。这时我并不知道可以设置执行优先级,在查找相关信息后终于大海捞针版找到一个帖子,函数属性 attribute ((constructor))和__attribute__ ((destructor)),至此问题终于得到解决,具体代码如下:

class A{
    public:
        string s;
    A() {
        printf("default structure.\n");
    }

    A(string _s): s(_s) {
        printf("parameter structer.\n");
    }

    void operator=(string _s) {
        this-> = _s;
        printf("operator=\n");
        return ;
    }

    ~A(){
        printf("delete\n");
    }
};

A a __attribute__((init_priority(102)));

__attribute__((constructor(103)))
void init() {
    a.emplace_back("abc");
    printf("a = %s\n", a.s.c_str());
}

int main() {
    printf("a = %s\n", a.s.c_str());
    a = "123";
    printf("a = %s\n", a.s.c_str());
    return 0;
}

运行结果:
在这里插入图片描述

    由运行结果可以看到全局变量a在进入初始化函数时已经完成初始化(构造),并且在主函数中也没有丢失初始化函数中所赋的数据,符合预期结果,按照上述操作后,vector<A> a同样可以正常在初始化函数中添加数据,问题得以解决。


最后说一个细节,在__attribute__()中无法使用cout输出信息,只能使用printf进行信息输出,找到的资料说的是:

cout 需要全局变量初始化,但是init()和全局构造函数比他执行的早。


引用文章:

https://www.oschina.net/question/4109409_2305038

https://blog.csdn.net/yao_zhuang/article/details/106797661

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值