【问题标题】:Runtime vs. Compile time运行时与编译时间
【发布时间】:2010-10-25 04:05:33
【问题描述】:

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

【问题讨论】:

  • 我举了一个很小但很清楚的例子.... 它并没有被巨大的细节吓倒。在那之后,所有的答案可能都会被解决。他们太棒了……

标签: language-agnostic runtime compile-time


【解决方案1】:

编译时间和运行时间之间的差异是头脑敏锐的理论家称之为phase distinction的一个例子。这是最难学习的概念之一,尤其是对于没有太多编程语言背景的人来说。要解决这个问题,我觉得问一下很有帮助

  1. 程序满足哪些不变量?
  2. 这个阶段会出现什么问题?
  3. 如果阶段成功,后置条件是什么(我们知道什么)?
  4. 如果有的话,输入和输出是什么?

编译时间

  1. 程序不需要满足任何不变量。事实上,它根本不需要是一个格式良好的程序。您可以将此 HTML 提供给编译器,然后观看它...
  2. 编译时可能出现的问题:
    • 语法错误
    • 类型检查错误
    • (很少)编译器崩溃
  3. 如果编译成功,我们知道什么?
    • 程序结构良好 --- 任何语言的有意义的程序。
    • 可以开始运行程序了。 (程序可能会立即失败,但至少我们可以尝试。)
  4. 什么是输入和输出?
    • 输入是正在编译的程序,以及任何头文件、接口、库或其他需要导入以进行编译的巫术。
    • 希望输出是汇编代码或可重定位的目标代码,甚至是可执行程序。或者如果出现问题,输出是一堆错误消息。

运行时间

  1. 我们对程序的不变量一无所知——它们是程序员输入的任何内容。运行时不变量很少由编译器单独强制执行。它需要程序员的帮助。
  2. 可能出错的是运行时错误

    • 除以零
    • 取消引用空指针
    • 内存不足

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

    • 试图打开不存在的文件
    • 尝试查找网页并发现所谓的 URL 格式不正确
  3. 如果运行时成功,则程序完成(或继续运行)而不会崩溃。
  4. 输入和输出完全取决于程序员。文件、屏幕上的窗口、网络数据包、发送到打印机的作业,应有尽有。如果程序发射导弹,这是一个输出,它只在运行时发生:-)

【讨论】:

  • 对它所涵盖的内容(+1)的回答非常好,但是您甚至没有涉及编译时与运行时的元编程方面,恕我直言,这是最有趣的部分。鉴于此答案已被接受,我承认它很可能超出了 OP 所寻找的范围。
  • 很好,如果有人在我的讲座中问我这个问题,我会用你的回答 :-)
  • 这是一个非常好的答案。它非常清晰易懂。在 Google 中找到这么明确的答案并不容易。
  • 即使你已经编程了一段时间,它仍然不容易获得......它不仅仅是新手。 OP的好问题。
  • "这个程序不需要满足任何不变量。事实上,它根本不需要是一个格式良好的程序。你可以把这个 HTML 提供给编译器,然后看着它吐..." I不知道你在说什么。你能用简单的话解释一下,而不是被所有这些技术垃圾所困扰吗?
【解决方案2】:

我从错误的角度来考虑它,以及何时可以捕获它们。

编译时间:

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

字符串值不能赋值为 int 类型的变量,所以编译器在编译时确定这段代码有问题

运行时间:

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

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

【讨论】:

  • 现在我们都可以理解了。这里没有一般的垃圾技术词。不错。
  • 对于 iPhone 应用程序:编译时间是开发人员第一次将代码编译成.app 扩展名吗?还是在每次用户启动应用程序时启动时发生?
  • @Honey 由开发者第一次编译成.app
  • 这是一个很好的底线答案,从概念上涵盖了编译和运行时之间的差异。我也很欣赏所选择的学术性、教授性的答案,但这个答案清晰简洁。读完这个答案后,我可以回去阅读选择的答案,这更有意义。谢谢
  • 简单明了。大量使用示例代码来帮助我们理解。
【解决方案3】:

编译时间:作为开发人员的您编译代码的时间段。

运行时间:用户运行您的软件的时间段。

您需要更清晰的定义吗?

【讨论】:

  • @BCS:OP 可能对使用解释或字节编译然后运行的一步式语言进行了非常简单的编程介绍,因此不需要区分。这个问题很幼稚,但不是愚蠢的。
  • @dmckee:我认为这个答案甚至不会对您的用户有用,因为它没有比原始问题更多的信息内容。任何会问这个答案的人都没有业务编程(我认为 OP 是在问这个问题)。
  • 我有一个简单的问题。当有人说典型的运行时错误是除以零时,如果你有一个变量怎么办,让我们说int x = 3/0,但你不对这个变量做任何事情。我们不打印它或任何东西。这是否仍会被视为运行时错误?
  • 对于 iPhone 应用程序:编译时间是开发人员第一次将代码编译成 .app 扩展名吗?还是每次用户启动应用程序时都会在启动时发生?如果它是编译开发人员代码的编译时间,那我为什么要关心它呢?我的意思是这不会影响用户体验吗?因为它只会浪费开发人员的时间!
  • @Robben 我假设你已经得到了你的答案,但我会为其他人回答。是的,即使你不使用它也会是一个运行时错误
【解决方案4】:

编辑:以下适用于 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)。试图用一个狡猾的数据库来解决一个损坏的表单,这让我非常难过!
【解决方案5】:

将源代码翻译成在[屏幕|磁盘|网络]上发生的事情可以(大致)以两种方式发生;称他们为编译和解释。

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

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

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

在一个解释程序中(例如MicroSoft basic(在dos上)和python(我认为)):

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

在这种情况下,编译时间和运行时间之间的差异更难确定,并且与程序员或用户的相关性更小。

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

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

【讨论】:

    【解决方案6】:

    基本上,如果您的编译器可以在“编译时”计算出您的意思或值是什么,它可以将其硬编码到运行时代码中。显然,如果你的运行时代码每次都必须进行计算,它会运行得更慢,所以如果你能在编译时确定一些东西,那就更好了。

    例如。

    不断折叠:

    如果我写:

    int i = 2;
    i += MY_CONSTANT;
    

    编译器可以在编译时执行此计算,因为它知道 2 是什么,以及 MY_CONSTANT 是什么。因此,它可以避免每次执行都执行计算。

    【讨论】:

    • 而且编译时代码比运行时绑定代码更容易维护。在编译时,您可以使用编译器来检查一些东西。运行时相同的东西需要更多时间来检查,因为涉及到测试。
    【解决方案7】:

    嗯,好吧,运行时是用来描述程序运行时发生的事情。

    编译时间用于描述在构建程序时发生的事情(通常是由编译器)。

    【讨论】:

      【解决方案8】:

      编译时间:

      在编译时完成的事情在结果程序运行时(几乎)不会产生任何成本,但在构建程序时可能会产生大量成本。

      运行时间:

      或多或少正好相反。构建时成本低,运行程序时成本更高。

      从另一边;如果某些事情是在编译时完成的,它只会在你的机器上运行,如果是运行时的事情,它就会在你的用户机器上运行。

      相关性

      这很重要的一个例子是单元携带类型。编译时版本(如Boost.Unitsmy version in D)最终与使用本机浮点代码解决问题一样快,而运行时版本最终不得不打包有关值所在单位的信息并在每次操作的同时对它们进行检查。另一方面,编译时版本要求值的单位在编译时已知,无法处理它们来自运行时输入的情况。

      【讨论】:

        【解决方案9】:

        作为其他答案的补充,以下是我向外行解释的方式:

        您的源代码就像一艘船的蓝图。它定义了船的制造方式。

        如果您将蓝图交给造船厂,而他们在建造船舶时发现了缺陷,他们会在船舶离开干船坞或接触水之前立即停止建造并向您报告。这是一个编译时错误。这艘船甚至从未真正漂浮或使用过它的引擎。发现错误是因为它甚至阻止了船的制造。

        当您的代码编译完成时,就好像这艘船正在完工。已建成并准备就绪。当你执行你的代码时,这就像在航行中发射船一样。乘客登机,发动机运转,船体在水面上,所以这是运行时间。如果你的船有一个致命的缺陷导致它在处女航中沉没(或者可能因为额外的头痛而在之后的某次航行),那么它就会遇到运行时错误。

        【讨论】:

          【解决方案10】:

          根据之前对问题What is the difference between run-time error and compiler error?的类似回答

          编译/编译时间/语法/语义错误: 编译或编译时间错误是由于输入错误而发生的错误,如果我们不遵循任何编程语言的正确语法和语义,则编译时间错误由编译器抛出。在您删除所有语法错误或调试编译时错误之前,它们不会让您的程序执行一行。
          示例:在 C 中缺少分号或将 int 错误输入为 Int

          运行时错误:运行时错误是程序处于运行状态时产生的错误。这些类型的错误会导致您的程序出现意外行为,甚至可能会终止您的程序。它们通常被称为例外。
          示例:假设您正在读取一个不存在的文件,将导致运行时错误。

          在此处阅读有关所有programming errors 的更多信息

          【讨论】:

            【解决方案11】:

            例如:在强类型语言中,可以在编译时或运行时检查类型。在编译时,这意味着如果类型不兼容,编译器会抱怨。在运行时意味着,您可以很好地编译您的程序,但在运行时,它会引发异常。

            【讨论】:

              【解决方案12】:

              以下是《JAVA 编程简介》的作者 Daniel Liang 关于编译的引述:

              “用高级语言编写的程序称为源程序或源代码。由于计算机无法执行源程序,因此必须将源程序翻译机器码 用于执行。翻译可以使用另一种称为解释器或编译器的编程工具来完成。” (丹尼尔·梁,"Introduction to JAVA programming",第 8 页)。

              ...他继续...

              “编译器将整个源代码翻译成机器代码文件,然后执行机器代码文件”

              当我们输入高级/人类可读的代码时,这首先是无用的!它必须在你的小 CPU 中转化为一系列“电子事件”!第一步是编译。

              简单地说:在这个阶段会发生编译时错误,而稍后会发生运行时错误。

              记住:程序编译时没有错误并不意味着它会运行时没有错误。

              在程序生命周期的就绪、运行或等待部分会发生运行时错误,而在生命周期的“新建”阶段之前会发生编译时错误。

              编译时错误示例:

              语法错误 - 如果代码不明确,如何将它们编译成机器级指令?您的代码需要 100% 符合语言的语法规则,否则无法编译为工作 machine code

              运行时错误示例:

              内存不足 - 例如,对递归函数的调用可能会导致给定特定程度的变量的堆栈溢出!编译器怎么能预料到这一点!?这不可以。

              这就是编译时错误和运行时错误的区别

              【讨论】:

                【解决方案13】:

                简而言之,b/w 编译时间和运行时间的区别。

                编译时:开发人员将程序以.java格式编写并转换为字节码,这是一个类文件,在此编译过程中出现的任何错误都可以定义为编译时错误。

                运行时:生成的 .class 文件被应用程序用于其附加功能,逻辑结果错误并引发运行时错误

                【讨论】:

                  【解决方案14】:

                  运行时间意味着当你运行程序时会发生一些事情。

                  编译时间意味着当你编译程序时会发生一些事情。

                  【讨论】:

                    【解决方案15】:

                    假设你是一个老板,你有一个助手和一个女仆,你给他们一个任务列表,助手(编译时)会抓取这个列表并检查任务是否可以理解并且你没有用任何尴尬的语言或语法写作,所以他知道你想分配某人担任工作,所以他为你分配了他,他明白你想要喝咖啡,所以他的角色结束了,女仆(运行时间)开始运行这些任务,所以她去给你煮咖啡,但突然间她没有找到要煮的咖啡,所以她停止煮咖啡,或者她采取不同的行动并给你泡茶(当程序的行动不同时,因为他发现错误)。

                    【讨论】:

                      【解决方案16】:

                      编译时间:

                      在编译时完成的事情在结果程序运行时(几乎)不会产生任何成本,但在构建程序时可能会产生大量成本。 运行时:

                      或多或少正好相反。构建时成本低,运行程序时成本更高。

                      从另一边;如果某些事情是在编译时完成的,它只会在你的机器上运行,如果是运行时的事情,它就会在你的用户机器上运行。

                      【讨论】:

                        【解决方案17】:

                        编译时间: 将源代码转换为机器代码以使其成为可执行文件所花费的时间称为编译时间。

                        运行时间: 当应用程序运行时,它被称为运行时。

                        编译时错误是那些语法错误,缺少文件引用错误。 运行时错误发生在源代码被编译成可执行程序之后并且程序正在运行时。例如程序崩溃、意外的程序行为或功能不起作用。

                        【讨论】:

                          【解决方案18】:

                          恕我直言,您需要阅读许多链接和资源来了解运行时与编译时之间的区别,因为它是一个非常复杂的主题。 我在下面列出了一些我推荐的图片/链接。

                          除了上面所说的,我想补充一点,有时一张图片价值 1000 字:

                          1. 这两个的顺序:先是编译时再运行 编译后的程序可以由用户打开和运行。当应用程序运行时,它被称为 runtime : 编译时间,然后是 runtime1 ;

                          CLR_diag 编译时间,然后是 runtime2

                           from Wiki  
                          

                          https://en.wikipedia.org/wiki/Run_time https://en.wikipedia.org/wiki/Run_time_(program_lifecycle_phase)

                          运行时、运行时或运行时可指:

                          计算

                          运行时间(程序生命周期阶段),计算机程序执行的时间段

                          运行时库,旨在实现编程语言内置功能的程序库

                          运行时系统,旨在支持计算机程序执行的软件

                          软件执行,在运行时阶段一条一条地执行指令的过程

                          编译器列表 https://en.wikipedia.org/wiki/List_of_compilers

                          • 在 google 上搜索并比较运行时错误与编译错误:

                          ;

                          1. 在我看来,有一件非常重要的事情要知道: 3.1 build vs compile 和 Build Lifecycle 的区别 https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

                          3.2 这三件事的区别:编译 vs 构建 vs 运行时

                          https://www.quora.com/What-is-the-difference-between-build-run-and-compile Fernando Padoan,一个对语言设计有点好奇的开发者 2月23日回答 关于其他答案,我要倒退:

                          运行是获取一些二进制可执行文件(或脚本,用于解释语言),嗯……作为计算机上的一个新进程执行; 编译是解析用某种高级语言(如果与机器代码相比更高)编写的程序,检查其语法、语义、链接库,可能进行一些优化,然后创建二进制可执行程序作为输出的过程。这个可执行文件可能是机器码的形式,或者是某种字节码——即针对某种虚拟机的指令; 构建通常涉及检查和提供依赖关系、检查代码、将代码编译成二进制文件、运行自动化测试并将生成的二进制文件和其他资产(图像、配置文件、库等)打包成某种特定格式的可部署文件。请注意,大多数过程是可选的,有些过程取决于您构建的目标平台。例如,为 Tomcat 打包 Java 应用程序将输出一个 .war 文件。用 C++ 代码构建 Win32 可执行文件可以只输出 .exe 程序,也可以将其打包到 .msi 安装程序中。

                          【讨论】:

                            【解决方案19】:

                            我一直认为它与程序处理开销以及它如何影响性能有关,如前所述。一个简单的例子是,要么在代码中定义我的对象所需的绝对内存。

                            定义的布尔值占用 x 内存,然后在编译的程序中并且不能更改。当程序运行时,它确切地知道要为 x 分配多少内存。

                            另一方面,如果我只是定义一个通用对象类型(即一种未定义的占位符,或者可能是一个指向某个巨型 blob 的指针),那么我的对象所需的实际内存在程序运行并分配之前是未知的一些东西,因此必须对其进行评估,然后内存分配等将在运行时动态处理(更多的运行时开销)。

                            动态处理的方式将取决于语言、编译器、操作系统、您的代码等。

                            然而,这实际上取决于您使用运行时与编译时的上下文。

                            【讨论】:

                              【解决方案20】:

                              这是对“运行时和编译时的区别?”问题的答案的扩展。 -- 与运行时和编译时相关的开销的差异?

                              产品的运行时性能通过更快地交付结果来提高其质量。通过缩短编辑-编译-调试周期,产品的编译时性能有助于其及时性。但是,运行时性能和编译时性能都是实现及时质量的次要因素。因此,只有在整体产品质量和及时性得到改善的情况下,才应考虑运行时和编译时性能的改进。

                              进一步阅读的重要来源here

                              【讨论】:

                                【解决方案21】:

                                我们可以将它们分为静态绑定和动态绑定两大类。它基于使用相应值完成绑定的时间。如果引用是在编译时解析的,那么它是静态绑定,如果引用是在运行时解析的,那么它是动态绑定。静态绑定和动态绑定也称为早期绑定和后期绑定。有时也称为静态多态和动态多态。

                                约瑟夫·库兰代‏.

                                【讨论】:

                                  【解决方案22】:

                                  运行时和编译时的主要区别是:

                                  1. 如果您的代码中有任何语法错误和类型检查,那么它会抛出编译时错误,其中 - 作为运行时:它会在执行代码后进行检查。 例如:

                                  int a = 1 int b = a/0;

                                  这里第一行末尾没有分号--->在执行操作b时执行程序后编译时错误,结果是无限--->运行时错误。

                                  1. 编译时不查找代码提供的功能的输出,而运行时查找。

                                  【讨论】:

                                    【解决方案23】:

                                    这是一个非常简单的答案:

                                    运行时和编译时是指软件程序开发的不同阶段的编程术语。 为了创建一个程序,开发人员首先编写源代码,它定义了程序将如何运行。小程序可能只包含几百行源代码,而大程序可能包含数十万行源代码。源代码必须编译成机器码才能成为可执行程序。这个编译过程称为编译时间。(将编译器视为翻译器)

                                    用户可以打开和运行已编译的程序。当应用程序运行时,它被称为运行时。

                                    程序员经常使用术语“运行时”和“编译时”来指代不同类型的错误。编译时错误是诸如语法错误或缺少文件引用之类的问题,它会阻止程序成功编译。编译器会产生编译时错误,通常会指出源代码的哪一行导致了问题。

                                    如果一个程序的源代码已经编译成可执行程序,它可能仍然存在程序运行时出现的错误。示例包括不起作用的功能、意外的程序行为或程序崩溃。这些类型的问题被称为运行时错误,因为它们发生在运行时。

                                    The reference

                                    【讨论】:

                                      【解决方案24】:

                                      看看这个例子:

                                      public class Test {
                                      
                                          public static void main(String[] args) {
                                              int[] x=new int[-5];//compile time no error
                                              System.out.println(x.length);
                                          }}
                                      

                                      以上代码编译成功,没有语法错误,完全有效。 但在运行时,它会抛出以下错误。

                                      Exception in thread "main" java.lang.NegativeArraySizeException
                                          at Test.main(Test.java:5)
                                      

                                      就像在编译时检查某些情况一样,在运行时检查某些情况后,一旦程序满足所有条件,您将获得输出。 否则会出现编译时或运行时错误。

                                      【讨论】:

                                        【解决方案25】:

                                        您可以通过阅读实际代码来了解代码编译结构。除非您了解所使用的模式,否则运行时结构并不清晰。

                                        【讨论】:

                                          【解决方案26】:
                                          public class RuntimeVsCompileTime {
                                          
                                              public static void main(String[] args) {
                                                  
                                                  //test(new D()); COMPILETIME ERROR
                                                  /**
                                                   * Compiler knows that B is not an instance of A
                                                   */
                                                  test(new B());
                                              }
                                              
                                              /**
                                               * compiler has no hint whether the actual type is A, B or C
                                               * C c = (C)a; will be checked during runtime
                                               * @param a
                                               */
                                              public static void test(A a) {
                                                  C c = (C)a;//RUNTIME ERROR
                                              }
                                          
                                          }
                                          
                                              class A{
                                              
                                          }
                                          
                                              class B extends A{
                                              
                                          }
                                          
                                              class C extends A{
                                              
                                          }
                                          
                                              class D{
                                              
                                          }
                                          

                                          【讨论】:

                                            【解决方案27】:

                                            这对 S.O. 来说不是一个好问题。 (这不是一个特定的编程问题),但总的来说这不是一个坏问题。

                                            如果您认为这是微不足道的:那么读取时间与编译时间呢?什么时候可以做出有用的区分?编译器在运行时可用的语言呢? Guy Steele(不是傻瓜,他)在 CLTL2 中写了 7 页关于 EVAL-WHEN 的内容,CL 程序员可以使用它来控制它。 定义,2句话勉强够用,而解释本身就远远不够。

                                            一般来说,这是一个语言设计者似乎试图避免的棘手问题。 他们经常只是说“这是一个编译器,它做编译时的事情;之后的一切都是运行时的,玩得开心”。 C 被设计为易于实现,而不是最灵活的计算环境。如果您没有在运行时可用的编译器,或者无法轻松控制何时评估表达式,您往往会以语言中的技巧来伪造宏的常见用法,或者用户想出设计模式来模拟拥有更强大的构造。一种易于实现的语言绝对是一个值得的目标,但这并不意味着它是编程语言设计的终极目标。 (我很少使用 EVAL-WHEN,但我无法想象没有它的生活。)

                                            围绕编译时和运行时的问题空间很大,而且很大程度上仍未被探索。这并不是说 S.O.是进行讨论的正确场所,但我鼓励人们进一步探索这个领域,尤其是那些对它应该是什么没有先入为主的概念的人。这个问题既不简单也不愚蠢,我们至少可以为调查官指出正确的方向。

                                            不幸的是,我不知道有什么好的参考资料。 CLTL2 讲了一点,但是不太适合学习。

                                            【讨论】:

                                            • 伙计,对你来说不是一个好的编程问题都是相对的。我认为这是一个很好的问题,也是我想了解更多的东西。是的,我知道一般的“概念”以及编译时间和运行时是什么,但我想知道在运行时与编译时真正发生的复杂性。当您进行编程时,这些复杂性很重要并且需要注意。这不是很具体,所以这就是他问的原因。我讨厌人们坐在这里说这样的一般性问题毫无价值,而这些问题对于任何开发人员来说都是最重要的问题。
                                            • 如果您看不到问题的价值,那就是您的问题。如果它是普遍的,那是有原因的。仅仅因为你不喜欢一般性的问题并不意味着世界就围绕着你认为有用的东西旋转。他有一定的意图提出这个问题,并且他想要一系列答案以更好地理解和定义两者。明白了吗?
                                            猜你喜欢
                                            • 1970-01-01
                                            • 1970-01-01
                                            • 2023-04-05
                                            • 1970-01-01
                                            • 2021-02-13
                                            • 2012-10-04
                                            • 1970-01-01
                                            • 2010-12-29
                                            • 2011-05-15
                                            相关资源
                                            最近更新 更多