3

出于显而易见的原因,C 编译器必须编译对其他共享库外部可见的所有函数,以便它们符合平台的调用约定和其他 ABI 要求。但是,我了解到,对于可以保证永远不会从外部模块调用的函数,不一定需要这样做。

编译器如何以及何时可以确定对于给定函数是否成立?

  • 静态函数仅对同一编译单元中的其他函数可见,因此将是此类破坏 ABI 优化的良好候选者。但是指向静态函数的函数指针仍然可以传递给其他模块。编译器是否尝试确定函数指针是否在代码中的任何位置传递?

  • gcc 编译器有一些扩展,允许将符号声明为默认、隐藏甚至是内部的,并且文档特别提到,这些信息可用于执行某些外部可见功能无法实现的优化。如果将函数指针传递给注释为内部函数的外部代码会发生什么?

帮助编译器执行尽可能多的优化,同时仍保证与其他库的互操作性的最佳方法是什么?我是否应该只使用编译器选项将所有函数定义为内部函数,并使用所有需要在外部可见的函数的属性覆盖它?

4

2 回答 2

1

C 标准要求在所有情况下,指向同一函数的两个指针比较相等。

如果您将符号声明为外部并且从不将指针传递给外部代码,编译器只能执行破坏 ABI 的技巧。

编译器是否尝试确定函数指针是否在代码中的任何位置传递?

是的,如果它想要执行此优化,它确实如此。编译器可以很容易地知道哪些函数对它们执行了函数指针衰减,所以知道你是否获取了函数的地址并不是什么大问题。保守地说,编译器可以假设所有函数指针都传递给外部代码,或者他们可能会尝试更高级的东西。

如果将函数指针传递给注释为内部函数的外部代码会发生什么?

没什么大不了的——它必须有效。

内部/外部可见性主要是关于可见性。编译器只能在相对少数情况下将其转化为破坏 ABI 的许可证。

我是否应该只使用编译器选项将所有函数定义为内部函数,并使用所有需要在外部可见的函数的属性覆盖它?

除非您的库仅由一个翻译单元组成,否则您会期望几乎所有功能都需要在外部可见。“外部但仅在我的库中”和“对所有人都外部”之间在 C 中没有有意义的区别。但是,理论上,你可以试试这个。但是,我怀疑您是否会实现很大的加速,对于一个不平凡的代码库来说,这将是一个很大的努力。

于 2013-12-04T10:11:08.250 回答
0

静态函数仅对同一编译单元中的其他函数可见,因此将是此类破坏 ABI 优化的良好候选者。但是指向静态函数的函数指针仍然可以传递给其他模块。编译器是否尝试确定函数指针是否在代码中的任何位置传递?

是的,编译器会进行“转义分析”以查看给定函数是否真的只在内部使用,或者它是否通过其指针转义。

gcc 编译器有一些扩展,允许将符号声明为默认、隐藏甚至是内部的,并且文档特别提到,这些信息可用于执行某些外部可见功能无法实现的优化。如果将函数指针传递给注释为内部函数的外部代码会发生什么?

请参阅我对您的第一点的回答。

于 2013-12-04T10:10:44.240 回答