为什么 -fno-objc-exceptions 标志会更改编译的 .o 文件的大小,即使 .m 中没有与异常相关的代码?



我重新编译了一个不使用 @try@catch@finally的文件,并且它变小20%。为什么会这?为什么Xcode不使用任何不使用这些关键字的文件?

tl; dr:您正在告诉编译器省略堆栈的放松信息,否则它将使用这些信息来帮助通过代码干净地传播异常。


对于背景,知道什么是例外,当它们被扔(并被捕获)时会发生什么。由于在线有大量详细资源涵盖该主题,我将在此处简要概述:

  • 当抛出异常(无论是在C 还是Objective-C中)时,异常和一些相关的信息将通过呼叫堆栈传递到可以处理它们的地方。这是通过称为"堆栈放松"的过程完成的 - 本质上,这就像一个函数的早期返回,该函数捕获了一些有关函数中返回发生的信息的信息
  • 要产生该信息(通常以回溯形式呈现),编译器需要嵌入有关如何在任意位置通过堆栈放松的信息(因为可以将例外扔在代码基础上,然后才能向前移动到大约在任何地方)
  • 在C,C ,Objective-C和Objective-C 中,Clang和GCC都使用C 异常机械来生成不符合堆栈的放松信息并传播异常(并处理C 和Objective-C中的异常)
  • 默认情况下,编译器打开-fexceptions,因为它无法分辨出异常可能会通过您的代码抛出。由于一个.m文件中的功能可以在其他.m文件中调用另一个函数( can can ford exception),因此在一般情况下,编译器要做的唯一安全的事情始终是启用异常和放松信息
  • 这些放松的信息,然后隐含地占据可执行文件中的空间。如果您要关闭放松的信息并告诉编译器"我确定此处的任何代码都会抛出任何例外",那么您可以通过-fno-exceptions在全球范围内关闭例外情况,或-fno-objc-exceptions用于转动Objective-C代码中的例外。(请注意,如果异常是仍然通过代码抛出的,那么您可能会得到一个漂亮的垃圾回溯,如果有的话)

gcc有有关-fexceptions标志的更多信息,默认情况下可以启用异常,但Clang具有相似的信息,尽管较少详细。

相关内容

最新更新