C++ 代码对象和可执行文件的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25896207/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between code object and executable file
提问by Piero Borrelli
I'm a C++ beginner and I'm studying the basics of the language. There is a topic in my book about the compiler and my problem is that I can not understand what the text wants to say:
我是 C++ 初学者,正在学习该语言的基础知识。我的书中有一个关于编译器的主题,我的问题是我无法理解文本想说的内容:
C++ is a compiled language so you need to translate the source code in a file that the computer can execute. This file is generated by the compiler and is called the object code ( .obj ), but a program like the "hello world" program is composed by a part that we wrote and a part of the C++ library. The linker links these two parts of a program and produces an executable file ( .exe ).
C++ 是一种编译语言,因此您需要将源代码翻译成计算机可以执行的文件。这个文件由编译器生成,称为目标代码( .obj ),但是像“hello world”程序这样的程序是由我们编写的一部分和 C++ 库的一部分组成的。链接器链接程序的这两个部分并生成一个可执行文件 ( .exe )。
Why does my book tell that the file that is executed by the computer is the one with the objsuffix (the object code) and then say that it is the one with the exesuffix?
为什么我的书上说计算机执行的文件是带有obj后缀(目标代码)的文件,然后说是带有exe后缀的文件?
回答by ArunasR
Object files are source compiled into binary machine language, but they contain unresolved external references (such as printf
,for instance). They may need to be linked against other object files, third party libraries and almost always against C/C++ runtime library.
目标文件被源代码编译成二进制机器语言,但它们包含未解析的外部引用(例如printf
,例如)。它们可能需要链接到其他目标文件、第三方库,并且几乎总是链接到 C/C++ 运行时库。
In Unix, both object and exe files are the same COFF format. The only difference is that object files have unresolved external references, while a.out files don't.
在 Unix 中,object 和 exe 文件都是相同的 COFF 格式。唯一的区别是目标文件有未解析的外部引用,而 a.out 文件没有。
回答by Basile Starynkevitch
The C++ specification is a technical document in English. For C++11have a look inside n3337(or spend a lot of money to buy the paperback ISO standard). In theory you don't need a computer to run a C++ program (you could use a bunch of human slaves, but that would be unethical, inefficient, and unreliable).
C++ 规范是英文的技术文档。对于C++11看看里面的n3337(或者花很多钱买平装 ISO 标准)。从理论上讲,您不需要计算机来运行 C++ 程序(您可以使用一群人类奴隶,但这不道德、低效且不可靠)。
You could have a C++ implementation which is an interpreter, not a compiler(e.g. Ch by SoftIntegration)
你可以有一个 C++ 实现,它是一个解释器,而不是一个编译器(例如SoftIntegration 的 Ch)
If you install Linux on your laptop (which I recommend doing to every student) then you could have several free softwareC++ compilers, in particular GCCand Clang/LLVM(using g++
and clang
commands respectively). Source files are suffixed .cc
, or .cxx
, or .cpp
, or even .C
(I prefer .cc
), and you could ask the compiler to handle a file of some other suffix as a C++ source file (but that is not conventional). Then, both object files(suffixed .o
) and executablesshare the same ELFformat. Conventionally, executables don't have any suffix (e.g. g++
is a binary executable, not doing much except starting other processes like cc1plus
-the compiler proper-, as
-the assembler-, ld
-the linker- etc...)
如果您在笔记本电脑上安装 Linux(我建议每个学生都这样做),那么您可以拥有多个免费软件C++ 编译器,特别是GCC和Clang/LLVM(分别使用g++
和clang
命令)。源文件的后缀是.cc
, or .cxx
, or .cpp
, 甚至.C
(我更喜欢.cc
),您可以要求编译器将其他后缀的文件作为 C++ 源文件处理(但这不是传统的)。然后,目标文件(后缀为.o
)和可执行文件共享相同的ELF格式。通常,可执行文件没有任何后缀(例如g++
是一个二进制可执行文件,没有做多少,除了启动其他程序一样cc1plus
-the编译proper-,as
-the汇编- ,ld
-the连接-等...)
In all cases I strongly recommend:
在所有情况下,我强烈建议:
- to enable all warnings and debug info during compilation (e.g. use
g++ -Wall -g
....) - to improve your source code till you got no warnings
- to learn how to use the debugger (
gdb
) - to be able to build your program on the command line
- to use a version control system like git
- to use a good editor like
emacs
,gedit
,geany
, orgvim
- once you are writing programs in several source files, learn how to use a builder like
make
- to learn C++11 (or even perhaps C++14) rather than older C++ standards
- to also learn other programming languages (Ocaml, Scheme, Haskell, Prolog, Scala, ....) since they would improve your thinking and your way of coding in C++
- to study the source code of several free software coded in C++
- to read the documentation of every function that you are using, e.g. on cppreferenceor in man pages(for Linux)
- to understand what is undefined behavior(the fact that your program sometimes work does not make it correct).
- 在编译期间启用所有警告和调试信息(例如使用
g++ -Wall -g
....) - 改进你的源代码,直到你没有警告
- 学习如何使用调试器 (
gdb
) - 能够在命令行上构建您的程序
- 使用像git这样的版本控制系统
- 使用像
emacs
,gedit
,geany
, 或gvim
- 一旦你在几个源文件中编写程序,学习如何使用像这样的构建器
make
- 学习 C++11(甚至可能是C++14)而不是旧的 C++ 标准
- 还可以学习其他编程语言(Ocaml、Scheme、Haskell、Prolog、Scala 等),因为它们会改善您的思维和 C++ 编码方式
- 研究几个用C++编码的自由软件的源代码
- 阅读您正在使用的每个函数的文档,例如在cppreference或手册页(对于 Linux)
- 了解什么是未定义的行为(您的程序有时无法正常工作的事实)。
Concretely, on Linux you could edit your Hello World program (file hello.cc
) with gedit
or emacs
(with a command like gedit hello.cc
) etc..., compile it using g++ -Wall -g hello.cc -o hello
command, debug it using gdb ./hello
, and repeat (don't forget to use git
commands for version control).
具体来说,在 Linux 上,您可以hello.cc
使用gedit
或emacs
(使用类似命令gedit hello.cc
)等编辑您的 Hello World 程序(文件),使用g++ -Wall -g hello.cc -o hello
命令编译它,使用调试它gdb ./hello
,然后重复(不要忘记使用git
命令进行版本控制) .
Sometimes it makes sense to generatesome C++ code, e.g. by some shell, Python, or awk
script (or even by your own program coded in C++ which generates C++ code!).
有时生成一些 C++ 代码是有意义的,例如通过一些 shell、Python 或awk
脚本(甚至通过你自己的用 C++ 编码的程序来生成 C++ 代码!)。
Also, understand that an IDEis nota compiler (but runs the compiler for you).
此外,要明白一个IDE是不是一个编译器(但运行编译器为你)。
回答by Richard Chambers
The languages used for programming computers along with the various software development tools have evolved over the years.
用于计算机编程的语言以及各种软件开发工具多年来一直在发展。
The first computers were programmed with numbers entered by switches on a console.
第一台计算机是用控制台上的开关输入的数字编程的。
Then people started developing languages and software that could be used to create software more easily and quicker. The first major development was creating assembler language where each line of source was converted by a computer program into a machine code instruction. Along with this came the development of linkers (which link pieces of machine code together into larger pieces). Assemblers were improved by adding a macro or preprocessor facility somewhat like the C/C++ Preprocessor though designed for assembly language.
然后人们开始开发可用于更轻松、更快速地创建软件的语言和软件。第一个主要发展是创建汇编语言,其中每一行源代码都由计算机程序转换为机器代码指令。随之而来的是链接器的开发(将机器代码片段链接成更大的片段)。汇编器通过添加宏或预处理器设施得到改进,有点类似于 C/C++ 预处理器,尽管它是为汇编语言设计的。
Then people created programming languages that looked more like people written languages rather than assembler (FORTRAN and COBOL and ALGOL for instance). These languages were easier to read and a single line of source might be converted into several machine instructions so it was more productive to write computer programs in these languages rather than assembler.
然后人们创造了看起来更像人类书写语言而不是汇编语言的编程语言(例如 FORTRAN、COBOL 和 ALGOL)。这些语言更容易阅读,一行源代码可能会被转换成多条机器指令,因此用这些语言而不是汇编语言编写计算机程序效率更高。
The C programming language was a later refinement using lessons learned from the early programming languages such as FORTRAN. And C used some of the same software development tools that already existed such as linkers which already existed. Still later C++ was invented, starting off as a refinement of C introducing object oriented facilities. In fact the first C++ compiler was really a C++ translator which translated C++ source code to C source code which was then compiled with a C compiler. However modern C++ is compiled straight to machine code in order to provide the full functionality of the C++ standard with templates, lambdas, and all the other things with C++11 and later.
C 编程语言是后来利用从早期编程语言(如 FORTRAN)中吸取的经验教训而改进的。C 使用了一些已经存在的相同软件开发工具,例如已经存在的链接器。再后来,C++ 被发明,开始是对 C 的改进,引入了面向对象的设施。事实上,第一个 C++ 编译器实际上是一个 C++ 翻译器,它将 C++ 源代码翻译成 C 源代码,然后用 C 编译器进行编译。然而,现代 C++ 直接编译为机器代码,以便提供 C++ 标准的全部功能,包括模板、lambda 以及 C++11 及更高版本的所有其他内容。
The basic steps for creating an application from a C or C++ source file are as follows: (1) the source files are created, (2) the source files are compiled (which is really two steps, Preprocessor and compilation), (3) the object files that are created by the C/C++ compiler are linked to create the .exe
从 C 或 C++ 源文件创建应用程序的基本步骤如下:(1)创建源文件,(2)编译源文件(实际上是两个步骤,预处理器和编译),(3)由 C/C++ 编译器创建的目标文件被链接以创建 .exe
So you have these steps of transforming one version of the computer program to another. The C++ source is compiled to produce the object files. The object files are then linked to produce the executable file.
所以你有这些将计算机程序的一个版本转换为另一个版本的步骤。编译 C++ 源代码以生成目标文件。然后链接目标文件以生成可执行文件。
When you run a program you run the executable file. The executable file contains several kinds of information. The first is the machine instructions that are the result of compiling the C++ source code. The other is information that the loader uses in order to know how to load the executable into memory.
当您运行程序时,您运行的是可执行文件。可执行文件包含多种信息。第一个是机器指令,它是编译 C++ 源代码的结果。另一个是加载器用来了解如何将可执行文件加载到内存中的信息。
In the old days, long long ago all libraries and object files were linked together into an executable file and the executable file was loaded by the loader and the loader was pretty simple.
在很久以前,所有的库和目标文件都被链接到一个可执行文件中,可执行文件由加载器加载,加载器非常简单。
Then people invented shared libraries and dynamic link libraries and this required the loader to be more complex. Not only does the loader have to load the executable file into memory so that it can start running, the loader must also find any shared libraries or dynamic link libraries that are also needed and load those too. And the loader also has to do a certain amount of linking of the additional components, the shared libraries, so the loader does a lot more than it used to do.
然后人们发明了共享库和动态链接库,这就要求加载器更加复杂。加载器不仅必须将可执行文件加载到内存中以便它可以开始运行,加载器还必须找到任何也需要的共享库或动态链接库并加载它们。而且加载器还必须对附加组件、共享库进行一定量的链接,因此加载器比以前做的要多得多。
回答by Pablo
Object code (within an object file): Output from a compiler intended as input for a linker (for the linker to produce executable code).
目标代码(在目标文件中):来自编译器的输出,旨在作为链接器的输入(用于链接器生成可执行代码)。
Executable: A program ready to be run (executed) on a computer
可执行文件:准备在计算机上运行(执行)的程序