代码对象和可执行文件之间的区别

Pie*_*lli 24 c++ linker

我是一名C++初学者,我正在研究该语言的基础知识.我的书中有一个关于编译器的主题,我的问题是我无法理解文本想要说的内容:

C++是一种编译语言,因此您需要将源代码转换为计算机可以执行的文件.该文件由编译器生成,称为目标代码(.obj),但像"hello world"程序这样的程序由我们编写的部分和C++库的一部分组成.链接器链接程序的这两部分并生成可执行文件(.exe).

为什么我的书告诉计算机执行的文件是带有obj后缀的文件(目标代码),然后说它是带有exe后缀的文件?

Aru*_*asR 36

目标文件是源代码编译成二进制机器语言,但它们包含未解析的外部引用(printf例如).它们可能需要与其他目标文件,第三方库以及几乎总是针对C/C++运行时库链接.

在Unix中,object和exe文件都是相同的COFF格式.唯一的区别是对象文件有未解析的外部引用,而a.out文件则没有.

  • 不,COFF在大多数Unix中已经过时了.他们使用(作为Linux)ELF! (14认同)
  • 真的,谢谢.不同的缩写,在问题的上下文中相同的差异! (3认同)

Bas*_*tch 10

C++规范是英文的技术文档.对于C++ 11,请查看n3337内部(或花费大量资金购买平装ISO标准).从理论上讲,你不需要一台计算机来运行一个C++程序(你可以使用一堆人类奴隶,但那是不道德的,低效的,不可靠的).

你可以有一个C++实现,它是一个解释器,而不是一个编译器(例如Ch by SoftIntegration)

如果你在笔记本电脑上安装Linux(我建议你对每个学生都这样做)那么你可以有几个免费软件 C++编译器,特别是GCCClang/LLVM(分别使用g++clang命令).源文件是后缀.cc,或者.cxx,或者.cpp甚至.C(我更喜欢.cc),你可以要求编译器处理一些其他后缀的文件作为C++源文件(但这不是常规的).然后,两个目标文件(后缀.o)和可执行文件共享相同的ELF格式.按照惯例,可执行文件没有任何后缀(比如g++是一个二进制可执行文件,没有做多少,除了启动其他程序一样cc1plus-the编译proper-,as-the 汇编 - ,ld-the 连接 -等...)

在所有情况下,我强烈建议:

  • 在编译期间启用所有警告和调试信息(例如使用g++ -Wall -g....)
  • 改进你的源代码,直到你没有警告
  • 学习如何使用调试器(gdb)
  • 能够在命令行上构建程序
  • 使用像git这样的版本控制系统
  • 使用一个好的编辑器一样emacs,gedit,geany,或者gvim
  • 一旦你在几个源文件中编写程序,学习如何使用像这样的构建器 make
  • 学习C++ 11(甚至可能是C++ 14)而不是旧的C++标准
  • 还学习其他编程语言(Ocaml,Scheme,Haskell,Prolog,Scala,....)因为它们可以改善你的思维和你在C++中的编码方式
  • 研究用C++编写的几个免费软件的源代码
  • 阅读您正在使用的每个函数的文档,例如在cppreference手册页中(对于Linux)
  • 了解什么是未定义的行为(您的程序有时工作的事实并不能使其正确).

具体而言,在Linux上,你可以编辑自己的Hello World程序(文件hello.cc用)geditemacs(用以下命令gedit hello.cc)等等,使用编译g++ -Wall -g hello.cc -o hello它使用命令,调试gdb ./hello,并重复(不要忘了使用git的命令进行版本控制) .

有时生成一些C++代码是有意义的,例如通过一些shell,Python或awk脚本(或者甚至是用C++编写的生成C++代码的程序!).

此外,要明白一个IDE不是一个编译器(但运行编译器为你).


Ric*_*ers 6

从 C 或 C++ 源文件创建应用程序的基本步骤如下:(1) 创建源文件(由人或由程序生成),(2) 编译源文件(实际上是两个步骤,预处理器和编译)转换为目标代码,(3)链接由 C/C++ 编译器创建的目标文件以创建 .exe

因此,您有将计算机程序的一个版本(源文件)转换为另一个版本(可执行文件)的步骤。编译 C++ 源代码以生成目标文件。然后链接目标文件以生成可执行文件。

在大多数情况下,在使用 C 和 C++ 进行编译和链接过程中会涉及多个不同的程序。每个程序接收某些文件并创建新文件。

  • C/C++预处理器接收源代码文件并生成源代码文件
  • C/C++ Compiler 接收源代码文件并生成目标代码文件
  • 链接器接收目标代码文件和库并生成可执行文件

请参阅- 1)预处理器,链接器,2)头文件,库之间有什么区别?我的理解正确吗?

大多数编译器安装都有一个程序可以为您运行这些不同的应用程序。因此,如果您正在使用,gcc那么gcc程序将首先运行 C++ 预处理器,然后是 C++ 编译器,然后是链接器。但是,您可以修改gcc命令行选项的作用,以告诉它仅运行 C++ 预处理器或仅编译源文件但不链接它们或仅链接目标代码文件。

计算机语言和编程简史

用于计算机编程的语言以及各种软件开发工具多年来一直在发展。

第一台计算机是用控制台上的开关输入的数字编程的。

然后人们开始开发可用于更轻松、更快速地创建软件的语言和软件。第一个主要发展是创建汇编语言,其中每一行源代码都由计算机程序转换为机器代码指令。随之而来的是链接器的开发(将机器代码片段链接成更大的片段)。汇编器通过添加宏或预处理器设施得到改进,有点类似于 C/C++ 预处理器,尽管它是为汇编语言设计的。

然后人们创造了看起来更像人类书写语言而不是汇编语言的编程语言(例如 FORTRAN、COBOL 和 ALGOL)。这些语言更容易阅读,一行源代码可能会被转换成多条机器指令,因此用这些语言而不是汇编语言编写计算机程序效率更高。

C 编程语言是后来利用从早期编程语言(如 FORTRAN)中吸取的经验教训而改进的。C 使用了一些已经存在的相同软件开发工具,例如已经存在的链接器。再后来,C++ 被发明,开始是​​对 C 的改进,引入了面向对象的设施。事实上,第一个 C++ 编译器实际上是一个 C++ 翻译器,它将 C++ 源代码翻译成 C 源代码,然后用 C 编译器进行编译。然而,现代 C++ 直接编译为机器代码,以便提供 C++ 标准的全部功能,包括模板、lambda 以及 C++11 及更高版本的所有其他内容。

链接器和加载器

当您运行程序时,您运行的是可执行文件。可执行文件包含多种信息。第一个是机器指令,它是编译 C++ 源代码的结果。另一个是加载器用来了解如何将可执行文件加载到内存中的信息。

在很久以前,所有的库和目标文件都被链接到一个可执行文件中,可执行文件由加载器加载,加载器非常简单。

后来人们发明了共享库和动态链接库,这就要求链接器更复杂,加载器更复杂。

链接器变得更加复杂,因为它必须能够识别使用共享库和静态库之间的区别,并且能够生成一个可执行文件,该文件不仅包含链接的目标代码,还包含有关任何动态库的加载程序信息.

加载器变得更加复杂,因为加载器不仅必须将可执行文件加载到内存中才能开始运行,加载器还必须找到任何同样需要的共享库或动态链接库并加载它们。而且加载器还必须对附加组件、共享库进行一定量的链接,因此加载器比以前做的要多得多。

也可以看看