【发布时间】:2010-10-25 04:05:33
【问题描述】:
运行时和编译时有什么区别?
【问题讨论】:
-
我举了一个很小但很清楚的例子.... 它并没有被巨大的细节吓倒。在那之后,所有的答案可能都会被解决。他们太棒了……
标签: language-agnostic runtime compile-time
运行时和编译时有什么区别?
【问题讨论】:
标签: language-agnostic runtime compile-time
编译时间和运行时间之间的差异是头脑敏锐的理论家称之为phase distinction的一个例子。这是最难学习的概念之一,尤其是对于没有太多编程语言背景的人来说。要解决这个问题,我觉得问一下很有帮助
可能出错的是运行时错误:
程序本身也可能检测到错误:
【讨论】:
我从错误的角度来考虑它,以及何时可以捕获它们。
编译时间:
string my_value = Console.ReadLine();
int i = my_value;
字符串值不能赋值为 int 类型的变量,所以编译器在编译时确定这段代码有问题
运行时间:
string my_value = Console.ReadLine();
int i = int.Parse(my_value);
这里的结果取决于 ReadLine() 返回的字符串。有些值可以解析为 int,有些则不能。这只能在运行时确定
【讨论】:
.app 扩展名吗?还是在每次用户启动应用程序时在启动时发生?
编译时间:作为开发人员的您编译代码的时间段。
运行时间:用户运行您的软件的时间段。
您需要更清晰的定义吗?
【讨论】:
int x = 3/0,但你不对这个变量做任何事情。我们不打印它或任何东西。这是否仍会被视为运行时错误?
(编辑:以下适用于 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
【讨论】:
将源代码翻译成在[屏幕|磁盘|网络]上发生的事情可以(大致)以两种方式发生;称他们为编译和解释。
在编译程序中(例如 c 和 fortran):
第一步发生的事情被称为发生在“编译时”,第二步发生的事情被称为发生在“运行时”。
在一个解释程序中(例如MicroSoft basic(在dos上)和python(我认为)):
在这种情况下,编译时间和运行时间之间的差异更难确定,并且与程序员或用户的相关性更小。
Java 是一种混合体,代码被编译成字节码,然后在虚拟机上运行,该虚拟机通常是字节码的解释器。
还有一种中间情况,程序被编译成字节码并立即运行(如在 awk 或 perl 中)。
【讨论】:
基本上,如果您的编译器可以在“编译时”计算出您的意思或值是什么,它可以将其硬编码到运行时代码中。显然,如果你的运行时代码每次都必须进行计算,它会运行得更慢,所以如果你能在编译时确定一些东西,那就更好了。
例如。
不断折叠:
如果我写:
int i = 2;
i += MY_CONSTANT;
编译器可以在编译时执行此计算,因为它知道 2 是什么,以及 MY_CONSTANT 是什么。因此,它可以避免每次执行都执行计算。
【讨论】:
嗯,好吧,运行时是用来描述程序运行时发生的事情。
编译时间用于描述在构建程序时发生的事情(通常是由编译器)。
【讨论】:
在编译时完成的事情在结果程序运行时(几乎)不会产生任何成本,但在构建程序时可能会产生大量成本。
或多或少正好相反。构建时成本低,运行程序时成本更高。
从另一边;如果某些事情是在编译时完成的,它只会在你的机器上运行,如果是运行时的事情,它就会在你的用户机器上运行。
这很重要的一个例子是单元携带类型。编译时版本(如Boost.Units 或my version in D)最终与使用本机浮点代码解决问题一样快,而运行时版本最终不得不打包有关值所在单位的信息并在每次操作的同时对它们进行检查。另一方面,编译时版本要求值的单位在编译时已知,无法处理它们来自运行时输入的情况。
【讨论】:
作为其他答案的补充,以下是我向外行解释的方式:
您的源代码就像一艘船的蓝图。它定义了船的制造方式。
如果您将蓝图交给造船厂,而他们在建造船舶时发现了缺陷,他们会在船舶离开干船坞或接触水之前立即停止建造并向您报告。这是一个编译时错误。这艘船甚至从未真正漂浮或使用过它的引擎。发现错误是因为它甚至阻止了船的制造。
当您的代码编译完成时,就好像这艘船正在完工。已建成并准备就绪。当你执行你的代码时,这就像在航行中发射船一样。乘客登机,发动机运转,船体在水面上,所以这是运行时间。如果你的船有一个致命的缺陷导致它在处女航中沉没(或者可能因为额外的头痛而在之后的某次航行),那么它就会遇到运行时错误。
【讨论】:
根据之前对问题What is the difference between run-time error and compiler error?的类似回答
编译/编译时间/语法/语义错误: 编译或编译时间错误是由于输入错误而发生的错误,如果我们不遵循任何编程语言的正确语法和语义,则编译时间错误由编译器抛出。在您删除所有语法错误或调试编译时错误之前,它们不会让您的程序执行一行。
示例:在 C 中缺少分号或将 int 错误输入为 Int。
运行时错误:运行时错误是程序处于运行状态时产生的错误。这些类型的错误会导致您的程序出现意外行为,甚至可能会终止您的程序。它们通常被称为例外。
示例:假设您正在读取一个不存在的文件,将导致运行时错误。
在此处阅读有关所有programming errors 的更多信息
【讨论】:
例如:在强类型语言中,可以在编译时或运行时检查类型。在编译时,这意味着如果类型不兼容,编译器会抱怨。在运行时意味着,您可以很好地编译您的程序,但在运行时,它会引发异常。
【讨论】:
以下是《JAVA 编程简介》的作者 Daniel Liang 关于编译的引述:
“用高级语言编写的程序称为源程序或源代码。由于计算机无法执行源程序,因此必须将源程序翻译成机器码 用于执行。翻译可以使用另一种称为解释器或编译器的编程工具来完成。” (丹尼尔·梁,"Introduction to JAVA programming",第 8 页)。
...他继续...
“编译器将整个源代码翻译成机器代码文件,然后执行机器代码文件”
当我们输入高级/人类可读的代码时,这首先是无用的!它必须在你的小 CPU 中转化为一系列“电子事件”!第一步是编译。
简单地说:在这个阶段会发生编译时错误,而稍后会发生运行时错误。
记住:程序编译时没有错误并不意味着它会运行时没有错误。
在程序生命周期的就绪、运行或等待部分会发生运行时错误,而在生命周期的“新建”阶段之前会发生编译时错误。
编译时错误示例:
语法错误 - 如果代码不明确,如何将它们编译成机器级指令?您的代码需要 100% 符合语言的语法规则,否则无法编译为工作 machine code。
运行时错误示例:
内存不足 - 例如,对递归函数的调用可能会导致给定特定程度的变量的堆栈溢出!编译器怎么能预料到这一点!?这不可以。
这就是编译时错误和运行时错误的区别
【讨论】:
编译时:开发人员将程序以.java格式编写并转换为字节码,这是一个类文件,在此编译过程中出现的任何错误都可以定义为编译时错误。
运行时:生成的 .class 文件被应用程序用于其附加功能,逻辑结果错误并引发运行时错误
【讨论】:
运行时间意味着当你运行程序时会发生一些事情。
编译时间意味着当你编译程序时会发生一些事情。
【讨论】:
假设你是一个老板,你有一个助手和一个女仆,你给他们一个任务列表,助手(编译时)会抓取这个列表并检查任务是否可以理解并且你没有用任何尴尬的语言或语法写作,所以他知道你想分配某人担任工作,所以他为你分配了他,他明白你想要喝咖啡,所以他的角色结束了,女仆(运行时间)开始运行这些任务,所以她去给你煮咖啡,但突然间她没有找到要煮的咖啡,所以她停止煮咖啡,或者她采取不同的行动并给你泡茶(当程序的行动不同时,因为他发现错误)。
【讨论】:
编译时间:
在编译时完成的事情在结果程序运行时(几乎)不会产生任何成本,但在构建程序时可能会产生大量成本。 运行时:
或多或少正好相反。构建时成本低,运行程序时成本更高。
从另一边;如果某些事情是在编译时完成的,它只会在你的机器上运行,如果是运行时的事情,它就会在你的用户机器上运行。
【讨论】:
编译时间: 将源代码转换为机器代码以使其成为可执行文件所花费的时间称为编译时间。
运行时间: 当应用程序运行时,它被称为运行时。
编译时错误是那些语法错误,缺少文件引用错误。 运行时错误发生在源代码被编译成可执行程序之后并且程序正在运行时。例如程序崩溃、意外的程序行为或功能不起作用。
【讨论】:
恕我直言,您需要阅读许多链接和资源来了解运行时与编译时之间的区别,因为它是一个非常复杂的主题。 我在下面列出了一些我推荐的图片/链接。
除了上面所说的,我想补充一点,有时一张图片价值 1000 字:
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
;
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 安装程序中。
【讨论】:
我一直认为它与程序处理开销以及它如何影响性能有关,如前所述。一个简单的例子是,要么在代码中定义我的对象所需的绝对内存。
定义的布尔值占用 x 内存,然后在编译的程序中并且不能更改。当程序运行时,它确切地知道要为 x 分配多少内存。
另一方面,如果我只是定义一个通用对象类型(即一种未定义的占位符,或者可能是一个指向某个巨型 blob 的指针),那么我的对象所需的实际内存在程序运行并分配之前是未知的一些东西,因此必须对其进行评估,然后内存分配等将在运行时动态处理(更多的运行时开销)。
动态处理的方式将取决于语言、编译器、操作系统、您的代码等。
然而,这实际上取决于您使用运行时与编译时的上下文。
【讨论】:
这是对“运行时和编译时的区别?”问题的答案的扩展。 -- 与运行时和编译时相关的开销的差异?
产品的运行时性能通过更快地交付结果来提高其质量。通过缩短编辑-编译-调试周期,产品的编译时性能有助于其及时性。但是,运行时性能和编译时性能都是实现及时质量的次要因素。因此,只有在整体产品质量和及时性得到改善的情况下,才应考虑运行时和编译时性能的改进。
进一步阅读的重要来源here:
【讨论】:
我们可以将它们分为静态绑定和动态绑定两大类。它基于使用相应值完成绑定的时间。如果引用是在编译时解析的,那么它是静态绑定,如果引用是在运行时解析的,那么它是动态绑定。静态绑定和动态绑定也称为早期绑定和后期绑定。有时也称为静态多态和动态多态。
约瑟夫·库兰代.
【讨论】:
运行时和编译时的主要区别是:
int a = 1
int b = a/0;
这里第一行末尾没有分号--->在执行操作b时执行程序后编译时错误,结果是无限--->运行时错误。
【讨论】:
这是一个非常简单的答案:
运行时和编译时是指软件程序开发的不同阶段的编程术语。 为了创建一个程序,开发人员首先编写源代码,它定义了程序将如何运行。小程序可能只包含几百行源代码,而大程序可能包含数十万行源代码。源代码必须编译成机器码才能成为可执行程序。这个编译过程称为编译时间。(将编译器视为翻译器)
用户可以打开和运行已编译的程序。当应用程序运行时,它被称为运行时。
程序员经常使用术语“运行时”和“编译时”来指代不同类型的错误。编译时错误是诸如语法错误或缺少文件引用之类的问题,它会阻止程序成功编译。编译器会产生编译时错误,通常会指出源代码的哪一行导致了问题。
如果一个程序的源代码已经编译成可执行程序,它可能仍然存在程序运行时出现的错误。示例包括不起作用的功能、意外的程序行为或程序崩溃。这些类型的问题被称为运行时错误,因为它们发生在运行时。
【讨论】:
看看这个例子:
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)
就像在编译时检查某些情况一样,在运行时检查某些情况后,一旦程序满足所有条件,您将获得输出。 否则会出现编译时或运行时错误。
【讨论】:
您可以通过阅读实际代码来了解代码编译结构。除非您了解所使用的模式,否则运行时结构并不清晰。
【讨论】:
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{
}
【讨论】:
这对 S.O. 来说不是一个好问题。 (这不是一个特定的编程问题),但总的来说这不是一个坏问题。
如果您认为这是微不足道的:那么读取时间与编译时间呢?什么时候可以做出有用的区分?编译器在运行时可用的语言呢? Guy Steele(不是傻瓜,他)在 CLTL2 中写了 7 页关于 EVAL-WHEN 的内容,CL 程序员可以使用它来控制它。 定义,2句话勉强够用,而解释本身就远远不够。
一般来说,这是一个语言设计者似乎试图避免的棘手问题。 他们经常只是说“这是一个编译器,它做编译时的事情;之后的一切都是运行时的,玩得开心”。 C 被设计为易于实现,而不是最灵活的计算环境。如果您没有在运行时可用的编译器,或者无法轻松控制何时评估表达式,您往往会以语言中的技巧来伪造宏的常见用法,或者用户想出设计模式来模拟拥有更强大的构造。一种易于实现的语言绝对是一个值得的目标,但这并不意味着它是编程语言设计的终极目标。 (我很少使用 EVAL-WHEN,但我无法想象没有它的生活。)
围绕编译时和运行时的问题空间很大,而且很大程度上仍未被探索。这并不是说 S.O.是进行讨论的正确场所,但我鼓励人们进一步探索这个领域,尤其是那些对它应该是什么没有先入为主的概念的人。这个问题既不简单也不愚蠢,我们至少可以为调查官指出正确的方向。
不幸的是,我不知道有什么好的参考资料。 CLTL2 讲了一点,但是不太适合学习。
【讨论】: