运行时 vs 编译时

483

运行时和编译时有什么区别?

26个回答

576
编译时间和运行时间的区别是所谓“阶段区分”理论的一个例子。这是最难学习的概念之一,特别是对于没有编程语言背景的人来说。为了解决这个问题,我发现问以下问题很有帮助:
1. 程序满足哪些不变量? 2. 在这个阶段可能出现什么问题? 3. 如果阶段成功,那么后置条件是什么(我们知道什么)? 4. 如果有输入和输出,它们是什么?

编译时间

  1. 该程序不需要满足任何不变量。实际上,它甚至不需要是一个规范的程序。您可以将此HTML输入编译器并观察其失败...
  2. 在编译时可能出现什么问题:
    • 语法错误
    • 类型检查错误
    • (很少发生)编译器崩溃
  3. 如果编译器成功了,我们会知道什么?
    • 该程序是规范的——无论使用哪种语言都是有意义的。
    • 可以开始运行程序。(程序可能立即失败,但至少我们可以尝试。)
  4. 输入和输出是什么?
    • 输入是要编译的程序,以及任何头文件、接口、库或其他必要的“巫术”,以便进行编译。
    • 输出是汇编代码、可重定位目标代码或甚至可执行程序。或者,如果出现问题,输出是一堆错误消息。

运行时

  1. 我们对程序的不变量一无所知——它们完全取决于程序员的设置。运行时不变量很少仅由编译器强制执行;它需要程序员的帮助。
  2. 可能出错的是运行时错误

    • 除以零
    • 解除引用空指针
    • 内存耗尽

    此外,程序本身也可能检测到错误:

    • 试图打开不存在的文件
    • 试图查找网页并发现一个URL格式不正确
  3. 如果运行成功,程序将完成(或继续运行)而不会崩溃。
  4. 输入和输出完全由程序员控制。文件、屏幕上的窗口、网络数据包、发送给打印机的任务等等都可以。如果程序发射导弹,那就是一种输出,只有在运行时才会发生 :-)

15
虽然你的回答很好(+1),但你没有涉及到编译时和运行时的元编程方面,我认为这是最有趣的部分。考虑到这个答案得到了采纳,我会承认这可能不是提问者想要的内容。 - BCS
13
这个答案非常好。它相当清晰易懂。在谷歌上很难找到这样清晰的答案。 - Tarik
7
即使您已经编程一段时间,理解这个也并不容易……这不仅仅是新手。OP提出了一个好问题。 - PositiveGuy
13
这个程序不需要满足任何不变条件,实际上,它甚至不需要是一个格式正确的程序。你可以把这段HTML代码交给编译器并观察它的错误信息。 - PositiveGuy
6
哈,这很有趣,将近500个人点赞了,但是十年来没有人解释这个神秘的“不变量”……最终jlau发表了评论,但以下是更清晰的解释:“不变量”是我们开发者应该遵循的一种“规则”,但编译器对此一无所知。感谢:https://softwareengineering.stackexchange.com/a/364286 - starriet
显示剩余7条评论

248

我会从错误以及它们何时可以被捕捉的角度来考虑。

编译时:

string my_value = Console.ReadLine();
int i = my_value;

一个字符串值不能被赋给 int 类型的变量,因此编译器在编译时就确定了这段代码存在问题。

运行时:

string my_value = Console.ReadLine();
int i = int.Parse(my_value);

这里的结果取决于ReadLine()返回的字符串是什么。有些值可以解析为整数,而另一些则不行。只能在运行时确定。


100
现在这是我们都能理解的东西。没有一般垃圾技术词汇。很好。 - PositiveGuy
对于 iPhone 应用程序:编译时间是指开发人员将代码编译成 .app 扩展名的第一次编译吗?还是每次用户启动应用程序时都会发生? - mfaani
1
@Honey,这是开发者第一次将其编译成 .app 文件。 - Maytham Fahmi
4
这是一个很好的、简明扼要的回答,概念上涵盖了编译和运行时的区别。我也很欣赏被选择的那个学术性、教授风格的回答,但这个回答更加清晰明了。阅读完这个回答后,我可以回去再读一遍被选择的回答,它现在更加有意义了。谢谢。 - mojave
简单明了。很好地运用示例代码帮助我们理解。 - silian-rail

111

编译时: 是指开发人员编译代码的时间周期。

运行时: 是指用户运行软件的时间周期。

您需要更清晰的定义吗?


17
@BCS:OP可能是通过使用解释型或一步编译运行的语言来进行编程的极其简单的介绍,因此从未需要区分。这个问题很天真,但不是愚蠢的。 - dmckee --- ex-moderator kitten
1
@dmckee:我认为这个答案甚至对你的用户也没有用处,因为它的信息内容不比原问题多。任何会问出这个答案所回答的问题的人都不应该从事编程(而且我不认为OP是在问那个问题)。 - BCS
我有一个疑问。当有人说典型的运行时错误是除以零,但是如果你有一个变量,比如 int x = 3/0,但你不对这个变量做任何事情,我们没有打印它或者其他什么操作。那么这仍然被认为是运行时错误吗? - Robben
对于 iPhone 应用程序:编译时间是指开发人员将代码编译成 .app 扩展名的第一次编译吗?还是每次用户启动应用程序时都会发生?如果是开发人员的代码被编译的编译时间,那么我为什么要关心它呢?我的意思是这不会影响用户体验,对吧?因为这只会浪费开发人员的时间! - mfaani
2
@Robben 我猜你这么长时间以后已经得到了答案,但我会为其他人回答。是的,即使你不使用它,它也会导致运行时错误。 - فربد ضروري
显示剩余3条评论

25

(编辑:以下内容适用于C#和类似的强类型编程语言。我不确定这是否能帮到你。)

比如,编译器将在编译时检测到以下错误,并导致编译错误,这样在运行程序之前就可以发现它:

int i = "string"; --> error at compile-time

另一方面,编译器无法检测到以下这种错误。您将在运行时(程序运行时)收到错误/异常。

Hashtable ht = new Hashtable();
ht.Add("key", "string");
// the compiler does not know what is stored in the hashtable
// under the key "key"
int i = (int)ht["key"];  // --> exception at run-time

异常处理。Hashtable 是其中之一,但我发现最大的进步是从 .net 1.1 到 .net 2.0,从无类型数据集转向有类型数据集(现在是 linq)。尝试修复一个带有不良数据库的破损表单曾经让我非常难过! - Spence

23

将源代码转换成在屏幕、磁盘或网络上发生的事情有大约两种方式,分别称为编译和解释。

编译程序中(例如c和fortran):

  1. 源代码输入另一个程序中(通常称为编译器),该程序会生成可执行程序(或错误信息)。
  2. 运行可执行文件(通过双击它或在命令行上键入它的名称)。

第一步发生的事情称为“编译时”,第二步发生的事情称为“运行时”。

解释程序中(例如MicroSoft basic(在dos上)和python(我想)):

  1. 源代码输入到另一个程序中(通常称为解释器),该程序直接“运行”它。此处解释器作为程序和操作系统(或在非常简单的计算机中是硬件)之间的中间层。

在这种情况下,编译时间和运行时间之间的差异比较难以确定,对程序员或用户来说也不那么重要。

Java是一种混合体,其中代码被编译为字节码,然后在虚拟机上运行,虚拟机通常是字节码的解释器。

还有一种中间情况,即将程序编译为字节码并立即运行(例如awk或perl)。


12
基本上,如果编译器能够在编译时确定您的意图或值,它可以将其硬编码到运行时代码中。显然,如果运行时代码每次都需要进行计算,那么运行速度会变慢,因此如果您可以在编译时确定某些东西,那就更好了。
例如:
常量折叠:
如果我写:
int i = 2;
i += MY_CONSTANT;
编译器能够在编译时执行此计算,因为它知道2是什么,MY_CONSTANT是什么。因此,这样可以避免在每次执行时进行一次计算。

编译时代码比运行时绑定代码更易于维护。在编译时,您可以使用编译器来检查一些内容。相同的内容在运行时需要更多时间来检查,因为涉及测试。 - user1154664

11

嗯,好的,"runtime"用于描述程序运行时发生的事情。

"Compile time"用于描述程序在构建过程中发生的事情(通常由编译器完成)。


11

编译时:

在编译时完成的操作在程序运行时几乎不会产生任何成本,但在构建程序时可能会产生大量成本。

运行时:

与之相反,构建时的成本较小,在程序运行时成本更高。

从另一方面来看;如果某些内容在编译时完成,那么它只能在您的计算机上运行。如果某些内容是在运行时完成的,则它将在用户的计算机上运行。

相关性

一个重要的例子是单位承载类型。编译时版本(例如 Boost.UnitsD中的我的版本)最终与使用本机浮点代码解决问题的速度一样快,而运行时版本最终必须携带关于值所在单位的信息,并在每个操作旁边执行检查。另一方面,编译时版本要求值的单位在编译时已知,并且无法处理来自运行时输入的情况。


11
作为其他答案的补充,以下是我如何向外行解释它的方法:
您的源代码就像一艘船的蓝图。它定义了船应该如何制造。
如果您将蓝图交给造船厂,他们在制造船时发现缺陷,他们将立即停止建造并向您报告,甚至在船从干船坞下水或接触水之前就它已经出现了编译时错误。这就是编译时错误。船甚至还没有真正漂浮或使用其引擎。因为它阻止了船只的制造所以发现了错误。
当您的代码被编译时,就像船已经完成。建造好并准备好出发了。当您执行代码时,就像将船投入航行。乘客上船,引擎启动,船体处于水中,这就是运行时间。如果您的船有致命缺陷,在赶赴处女航(或者后面的某次航行)的途中沉没,那么它就遭遇了运行时错误。

9

接下来是对之前类似问题的回答进行的跟进,问题链接为What is the difference between run-time error and compiler error?

编译错误/编译时错误/语法错误/语义错误:编译错误是由于拼写错误引起的错误,如果我们没有遵循任何编程语言的正确语法和语义,那么编译器会抛出编译错误。它们不会让你的程序执行一行代码,直到你消除所有语法错误或调试编译时错误。
例如:在C语言中缺少分号或将int误输入为Int

运行时错误:运行时错误是在程序运行时生成的错误。这些类型的错误会导致您的程序行为异常或甚至可能使您的程序崩溃。它们通常被称为异常。
例如:假设您正在读取一个不存在的文件,将导致运行时错误。

在此处阅读更多关于所有编程错误的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接