首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C编译器在静态链接到.a文件时是否放弃未使用的函数?

C编译器在静态链接到.a文件时是否放弃未使用的函数?
EN

Unix & Linux用户
提问于 2022-09-02 12:14:15
回答 3查看 5.6K关注 0票数 31

假设我有一个C程序main.c,它静态地链接到libmine.a。静态地链接到库会导致库函数在编译时嵌入到主可执行文件中。

如果libmine.a要使用main.c没有使用的函数,编译器(例如GCC)会放弃这些函数吗?

这个问题的灵感来源于使用静态库使可执行文件更大的“公共消息传递”,所以我很好奇编译器是否至少从归档文件中删除了未使用的代码。

EN

回答 3

Unix & Linux用户

回答已采纳

发布于 2022-09-02 12:26:33

在您的示例中,可执行文件将最终包含来自main.c (main.o)的代码,以及提供main.c使用的所有函数所需的来自libmine.a的任何对象文件(这是对象文件的存档)。

因此,链接器不一定包括所有的libmine.a,但是它可以使用的粒度不是函数(默认情况下),而是对象文件(严格地说,是节)。这样做的原因是,当将给定的.c文件编译为对象文件时,源代码中的信息就会丢失;特别是,函数的结束不会被存储,只存储它的开始,而且由于可以组合多个函数,因此很难从对象文件中确定如果函数未使用会实际删除什么。

但是,如果编译器和链接器能够访问所需的额外信息,它们就有可能做得更好。例如,80年代Mac上的LightspeedC编程环境可以使用项目作为库,而且由于在这种情况下它有完整的源代码,所以它只包含实际需要的函数。

在更现代的系统中,编译器可以被告知生成允许链接器单独处理函数的对象文件。使用GCC,在启用.o选项的情况下构建-ffunction-sections -fdata-sections文件,并将最终程序与--gc-sections选项链接起来。这确实会产生影响,特别是通过阻止某些类别的优化;有关详细信息,请参阅GCC中的废函数

与现代编译器和链接器一起使用的另一个选项是链接时间优化;使用-flto启用此选项。当启用优化时(例如,编译对象文件时的-O2 ),链接器将不会在生成的二进制文件中包含未使用的函数。即使没有-ffunction-sections -fdata-sections,这也是可行的。

票数 35
EN

Unix & Linux用户

发布于 2022-09-02 12:26:08

是。但是它是在模块级别上,而不是在函数上。

例如,您有两个源文件: foo_goo.c和bar.c

代码语言:javascript
运行
复制
// foo_goo.c
int foo() { .. };
int goo() { .. };
代码语言:javascript
运行
复制
// bar.c
int bar() { .. };

将它们编译成foo_goo.obar.o,并将两个.o放到归档libmine.a中。

现在,在您的main()中,您只调用foo()函数。

代码语言:javascript
运行
复制
// main.c
int main(int argc, char **argv) {
   return foo();
}

将此源文件编译为main.o并与.a链接。

链接器将在模块foo()中看到函数foo_goo.o并使用它,main()将引用foo()函数,goo()函数将被添加到最终的二进制文件中,但不会被重新修改。bar.o将被忽略,因为其中没有引用任何名称。

票数 13
EN

Unix & Linux用户

发布于 2022-09-03 09:17:09

这与编译器无关。如果使用静态链接,则是将所需的所有对象放到一个文件中的链接器。

这将是C程序的main()函数,所有可能由main使用的东西,任何可能被main使用的东西,可能被main使用的东西所使用的所有东西,等等。如果有一个函数不可能被调用,或者一个对象不可能被访问,那么链接器可以忽略它。如果一个对象文件包含五个可以调用的函数和十个不能调用的函数,那么链接器可能只包含前五个函数。

票数 -1
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/715899

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档