从c析构函数不起作用,来看gcc中的编译参数--whole-archive和--no-whole-archive

背景

最近遇到一个问题,就是驱动的析构函数未执行。将整个代码可以简化为如下形式。

+ testlib.c
#include <stdio.h>

__attribute__((constructor)) void print_hello()
{
	printf("hello world!\n");
}
+ main.c
#include <stdio.h>

int main()
{
	return 0;
}

编译脚本

#!/bin/sh
gcc -c testlib.c
ar -rsv  testlib.a testlib.o
gcc -o main main.c testlib.a

执行./main,没有输出。

原因分析

当把静态库链接到可执行程序时,链接器默认情况下只会提取所需的目标文件(或符号)来满足程序的需求。这意味着,如果静态库中的某个目标文件没有被引用到,那么该目标文件不会被包含在最终的可执行程序中。最终析构函数未被执行。

解决方法

通过编译参数 -Wl,--whole-archive导入静态库所有符号表解决。
调整后的编译脚本

#!/bin/sh
gcc -c testlib.c
ar -rsv  testlib.a testlib.o
gcc -o main main.c -Wl,--whole-archive testlib.a -Wl,--no-whole-archive

这里介绍一下这2个编译参数的作用,它们是GCC编译器的一个选项,用于控制链接器对静态库的处理方式。一般的用法是 -Wl,–whole-archive 和 -Wl,–no-whole-archive。

链接静态库的时候,默认情况下,链接器只会提取所需的目标文件(或符号)来满足程序的需求。这意味着,如果静态库中的某个目标文件没有被引用到,那么该目标文件不会被包含在最终的可执行程序中。

然而,有时候我们希望强制链接器将整个静态库包含在最终的可执行程序中,而不管其中的目标文件是否被引用。这时可以使用 --whole-archive 选项来实现。

不过,–whole-archive 选项的作用范围是全局的,它会将所有的静态库都包含进最终的可执行程序中,而不管是否被引用。这可能会导致最终的可执行程序变得庞大,包含了不必要的目标文件。

为了解决这个问题,可以使用 --no-whole-archive 选项。–no-whole-archive 选项告诉链接器停止将整个静态库包含在最终的可执行程序中。这样,链接器只会提取所需的目标文件来满足程序的需求。

综上所述,
–whole-archive 强制链接器将整个静态库文件符合包含在最终的可执行程序中,缺点会导致可执行文件变大。
–no-whole-archive 只包含所需的目标文件包含在最终的可执行程序中。

参考链接:
https://stackoverflow.com/questions/1202494/why-doesnt-attribute-constructor-work-in-a-static-library

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值