为什么生成的二进制文件如此之大?

时间:2011-05-09 06:41:32

标签: c++ size binaries

为什么编译C ++程序时生成的二进制文件如此之大(如同源代码文件大小的10倍)?与没有必要进行编译的解释语言相比,它提供了哪些优势(因此程序大小只是代码文件的大小)?

4 个答案:

答案 0 :(得分:9)

现代解释语言通常会将代码编译为某种表示方式,以便更快地执行...它可能无法写入磁盘,但肯定无法保证程序以更紧凑的形式表示。一些解释器完全耗尽并生成机器代码(例如Java JIT)。然后是解释器本身就位于内存中,这可能很大。

几点:

  • 源代码中的命令越复杂,执行它们可能需要的机器代码操作就越多。因此,更高级别的语言特征往往具有更高的编译代码与源代码的比率。这不一定是坏事:把它想象成“我只需要说一点我想做什么,它就会推断出所有必要的步骤”。编程中的挑战是确保它们必要 - 这需要良好的库和程序设计。
  • 编译器经常故意决定交换一些可执行文件大小以获得更快的预期执行速度:内联与外线代码是这种折衷的一部分,但对于小功能而言,它们可能不会一直更紧凑。
  • 更复杂的运行时环境(例如,添加对C ++异常的支持)可能涉及一些额外的代码,这些代码在程序首次开始为该语言功能构建必要的环境时运行。
  • 库功能可能无法比较。除了那些你很可能不得不追踪自己并且非常了解使用(例如XML,PDF解析,OpenGL)的附加库,语言通常会悄悄地使用支持库来实现语言功能和功能。任何这些都可能令人惊讶地大。
    • 例如,许多解释器只公开C库的printf()语句或类似的东西,而对于输出格式化,C ++有ostream - 一个更复杂,可扩展和类型安全的系统(为了更好或者更糟糕的是,跨函数调用的持久状态,查询和设置该状态的例程,可定制缓冲的附加层,可自定义的字符类型和本地化,以及通常可以导致更小的许多小内联函数较大的程序取决于确切的用途和编译器设置。什么是最好的取决于您的应用程序和内存与性能目标。
  • 内置语言语句的编译方式可能不同:整数表达式为switch,并且有100个案例标签随机分布在1到1000之间:一个编译器/语言可能决定“打包”100个案例并执行二进制文件搜索匹配,另一个使用稀疏填充的1000个元素的数组并进行直接索引(这会浪费可执行文件中的空间,但通常会使代码更快)。因此,很难根据可执行文件大小得出结论。

通常,随着程序变得越来越大,越来越复杂,内存使用和执行速度变得越来越重要。您没有看到以解释语言编写的操作系统,企业Web服务器或全功能商用文字处理器等系统,因为它们没有可扩展性。

答案 1 :(得分:7)

解释的语言假设在大多数情况下编译程序是独立的,可以使用解释器。

答案 2 :(得分:1)

采取一个简单的案例:假设你有一个单行程序

print("hello world")

“打印”是做什么的?当然很明显你要求其他代码做一些工作吗?并且该代码不是免费的,需要运行的总和远远超过您编写的代码行。在更现实的程序中,您可以利用许多复杂的库来管理窗口和其他UI功能,网络,数据库等。现在,无论该代码是捆绑到您的应用程序中还是从DLL加载,或者是否存在于解释器中,它都必须位于某个地方。

在编译和解释之间以及Java的编译/字节码交互方法等中间解决方案之间存在大量的交易。例如,您可以考虑

  • 每次运行时解释源代码的运行时成本与运行已编译代码的运行时成本
  • 解释器的可移植性优势 - 您需要为不同的平台编译不同版本的应用程序。

答案 3 :(得分:1)

通常,程序是用更高级的语言编写的,这些程序要由CPU执行,程序必须转换为机器代码。此转换由 编译器 解释器 完成。

编译器 只进行一次转换,而 解释器 通常会在每次程序转换时进行转换执行。

解释程序的运行速度比编译程序慢得多 ,因为解释器必须在每次执行时分析程序中的每个语句,然后执行所需的操作,而编译代码只是在由编译确定的固定上下文中执行操作(这是存在大型二进制文件的原因)。

口译员的另一个缺点是 他们必须作为附加软件 出现在环境中才能运行源代码。