C++ 是什么意思?程序需要运行吗?
这个问题已经困扰我有一段时间了。让我们考虑以下两个程序:
#incude <iostream>
int main()
{
std::cout << "Hello, World!";
}
和
int main()
{
int x = 5;
int y = x*x;
}
- Windows: 第一个示例自然需要一些用于控制台的系统 .dll。我明白这一点。第二个呢?它需要什么东西才能运行吗?一些运行时库?顺便问一下,运行时库实际上是做什么的?
- Linux: 不知道,能赐教一下吗?
我知道这取决于编译器和操作系统,但我需要一般答案或特定示例。 TIA。
This question has been bothering me for a while now. Let's consider the two following programs:
#incude <iostream>
int main()
{
std::cout << "Hello, World!";
}
and
int main()
{
int x = 5;
int y = x*x;
}
- Windows:
The first example, naturally, requires some system .dll's for the console. I understand that. What about the second? Does it need anything to run? Some runtime libraries? By the way, what do runtime libraries actually do? - Linux:
No idea, can you enlighten me?
I know it depends on the compiler and OS, but I need either a general answer or particular examples. TIA.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
作为一般答案,第一个需要 C++ 运行时库(支持标准库调用所需的东西)。它们在语言和支持库之间形成了某种接口,而支持库又知道如何在给定环境中实现它们的功能。
第二个不使用运行时库。它将使用 C 启动和终止代码(初始化和销毁 C 环境),但这是关于这些是否被视为运行时库的一部分的讨论点。如果你认为它们是一部分,那么,是的,它们将会被使用。它可能会使用非常很小的部分,因为启动代码和流内容之间的大小通常有很大差异。
您可以将代码静态(在链接时绑定)与运行时库链接,也可以动态链接(以便实际绑定在加载时完成)。对于 Windows 和 Linux 都是如此。
As a general answer, the first will require the C++ runtime libraries (the stuff you need to support the standard library calls). These form an interface of sorts between the language and the support libraries, which in turn know how to achieve what they do in the given environment.
The second makes no use of the runtime libraries. It will use the C startup and termination code (that initialises and tears down the C environment) but it's a discussion point as to whether or not these are considered part of the runtime libraries. If you consider them a part, then , yes, they will be used. It will probably be a very small part used since there's usually a big difference in size between startup code and the streams stuff.
You can link your code statically (binding at link time) with runtime libraries or dynamically (so that the actual binding is done at load time). That's true for both Windows and Linux.
对于 Windows 应用程序,您可以使用 Dependency Walker 查看所有依赖项。
For Windows applications you can use the Dependency Walker to see all dependencies.
第一个程序执行流 I/O,这意味着它必须与操作系统管理的资源(控制台、GUI)进行交互。因此,最终必须通过系统 dll 中实现的 API 来调用操作系统。
在 Windows 上,第二个程序不需要库。我相当确定 Linux 上也是如此。
The first program performs stream I/O, which means it has to interact with resources (console, gui) managed by the OS. So, ultimately, the OS has to be invoked via an API implemented in a system dll.
On windows the second program requires no libraries. I'm fairly sure the same is true on Linux.
使用 GCC 编译它们,并获得名为“hi”的可执行文件,在控制台中 write:
将为您提供连接到您的程序的共享对象(动态库)。
为了快速回答,这里有一个输出:
Compile them with GCC, and get executable named 'hi', in console write:
will give you the shared objects(dynamic libraries) which are connected to your program.
Just for quick answer here is an output:
好吧,让我们从更一般的角度来看待这个问题:
首先,您需要一台具有兼容 CPU 的计算机,该 CPU 可以与编译器输出的目标计算机配合使用。您可能认为这是显而易见的,但假设代码编译为 x86 机器代码,它不会在使用不同指令的 Alpha CPU 上运行。或者,如果编译为 x64 机器代码,它就无法在纯 x86 CPU 上运行。因此,运行 C++ 程序需要正确的硬件,而 Java 等基于虚拟机的语言则将其抽象化。
您还需要正确的操作系统。我不是移植程序方面的专家,但我认为不可能用 C++ 构建在多个操作系统上运行的单个可执行文件。例如,即使将第二个示例编译到 Windows,在实际调用
main()
函数之前和之后,也会在幕后产生大量运行时库代码。这将执行诸如准备堆和初始化 CRT 库之类的操作。 Windows 的 CRT 是通过 Windows API 实现的。您可以静态链接该库,因此不需要 CRT DLL,但程序中的代码仍然调用 Windows API,因此仍然依赖于平台。作为实验,我使用 Visual Studio 在 Windows 上编译了一个具有静态链接的空程序,根据 Dependency Walker 的说法,它仍然引用 KERNEL32.DLL 来实现HeapCreate
和ExitProcess
等函数。因此,“空”程序仍然会为您执行一大堆操作系统操作,以准备执行一些有用的操作(无论您的程序是否执行任何有用的操作)。另请注意,可能存在最低操作系统版本:由于对
EncodePointer
和DecodePointer
的调用,即使是空程序,Visual Studio 2010 也需要 Windows XP SP2 或更高版本。请参阅此问题< /a>.系统必须有内存可用于启动您的程序。您可能认为它什么也没做,但如上所述,在调用
main()
之前,程序的库会进行整个操作系统初始化调用。这些可能需要一些内存以及执行它所需的处理时间。根据操作系统的配置,您可能需要足够的安全权限来启动可执行程序。
因此,简而言之,要运行空的 C++ 程序(即使使用静态链接),您需要正确的 CPU、操作系统、运行可执行文件的权限以及完成程序的内存/处理时间。与 Java 或 .NET 等 VM 技术相比,要求可能会减少到仅需要正确的虚拟机、必要的权限以及运行程序所需的内存/CPU 时间。这可能不像听起来那么简单:您可能需要正确的虚拟机版本,例如 .NET Framework 4.0。这可能会使您的分发过程变得复杂,因为更新计算机的整个 JVM 或 .NET 框架可能是一个耗时的过程,需要管理员权限,并且可能需要 Internet 连接。在某些狭隘的情况下,这可能会破坏交易,因为在极少数情况下,可能更容易说“它将在自 XP 以来的任何 x86 兼容 Windows 操作系统上运行”,而不是“任何具有最新虚拟机的计算机”昨天才发布的机器”。不过,对于大多数用途来说,虚拟机允许您(理论上)忘记 CPU 和操作系统,这使得程序的分发变得更加容易;对于 C++,您至少需要为您想要支持的每个平台和 CPU 组合编译单独的可执行文件,无论您正在使用的库有什么额外要求。
Well, let's look at this from a more general point of view:
To start with, you'll need a computer with a compatible CPU that works with target machine of the compiler output. You might think this is obvious but assuming that code compiles to x86 machine code, it won't run on an Alpha CPU which uses different instructions. Alternatively, if you compile to x64 machine code, it won't run on an x86-only CPU. So the correct hardware is necessary to run the C++ program, in contrast to virtual-machine based languages like Java, which abstract that away.
You will also need the correct operating system. I'm not an expert on porting programs but I don't think it's possible to build a single executable that runs on multiple operating systems in C++. For example, compiling even your second example to Windows will have a lot of runtime-library code behind the scenes before and after the actual call to your
main()
function. This will do things like prepare the heap and initialise the CRT library. The CRT for Windows is implemented via the Windows API. You can static link the library so no CRT DLL is required, but the code in your program still makes calls to the Windows API, so is still platform dependent. As an experiment I compiled an empty program with static linking on Windows with Visual Studio, and according to Dependency Walker it still references KERNEL32.DLL for functions likeHeapCreate
andExitProcess
. So the 'empty' program still does a whole bunch of operating system stuff for you, in preparation for doing something useful (regardless of whether or not your program does anything useful).Also note there may well be a minimum operating system version: Visual Studio 2010 requires Windows XP SP2 or above for even an empty program, due to calls made to
EncodePointer
andDecodePointer
. See this question.The system will have to have the memory available to launch your program. You may think it does nothing, but as above demonstrates, before
main()
is called a whole load of OS initialization calls are made by your program's library. These probably require some memory, and the processing time necessary to execute it.Depending on the configuration of the operating system, you may need sufficient security privileges to launch executable programs.
So, in short, to run an empty C++ program even with static linking, you need the right CPU, operating system, permission to run the executable, and memory/processing time to complete the program. Compared to VM technologies like Java or .NET, the requirements would reduce to probably just the correct virtual machine, necessary privilege, and necessary memory/CPU time to run the program. This may not be as simple as it sounds: you might need the correct version of a virtual machine, such as .NET framework 4.0. This can complicate your distribution process since updating the entire JVM or .NET framework for a machine can be a time consuming process requiring administrator privileges and maybe an internet connection. In some narrow cases, this could be a deal breaker, since on rare occasions it may be easier to be able to say "it will run on any x86-compatible Windows operating system since XP" as opposed to "any machine with the latest virtual machine that was only released yesterday". For most purposes, though, the fact the virtual machine allows you to (in theory) forget about the CPU and operating system makes the distribution of the program easier; with C++, you are required to at least compile separate executables for each combination of platform and CPU you want to support, regardless of the additional requirements of the libraries you're using.
Windows 上的 C 程序需要 Windows 附带的 CRT 库。 C++ 有时需要所谓的“C++ 可再发行组件”。它们可以通过链接嵌入到应用程序中,但这将使 EXE 更大。
C programs on Windows require CRT libraries that come with Windows. C++ sometimes require so called "C++ redistributable". They can be embedded in app via linking but this will make EXE bigger.
对于您问题的第一部分 - 几位成员已经回答了您。
但我所说的是一般性的,并且是两种情况所必需的 - (如果您不知道的话)
对于任何要运行的程序,都必须为其提供所需的资源。在回答第一部分时,团队已经列出了几项。
但一般来说,它需要的是明确定义的地址空间(在主存中)、其属性和 CPU 时间。操作系统确保您在执行程序时得到这一点。除非有一些荒谬的冲突,否则你的程序就会得到这个(这就是为什么我猜 Chubsdad 评论“你需要运气”)。
操作系统调度、CPU 要求从内存中获取指令/数据然后执行它……所有这些都形成了一个执行程序的“机器”。
找到入口点(或程序中要执行的第一个点)是在编译时(例如 main 函数)或使用某些系统调用(如 exec() (在 Unix 中)/ CreateProcess()加载程序时决定的) )(在窗口中)。
For the 1st part of your question - you have been answered by several members.
But What I am saying is general and required for both cases - (in case you are not aware of)
For any program to run, it has to be provided with resources it needs. While answering 1st part team has already listed several items.
But in general, what it needs is well defined address space (in main memory), its properties and CPU time. Operating System ensures you get that when you execute your program. Unless there is some ridiculous conflict your program will get that (and that's why I guess Chubsdad commented "you need luck").
OS scheduling, CPU asking to fetch instructions/data from memory and then the executing it... all forms a "machine" that executes your program.
Finding the entry point (or first point in your program to execute) is all that is decided either at compile time (main function for example) or while you load your program using some system call like exec() (in Unix) / CreateProcess() (in windows).
在 Linux 上,任何 C 程序都静态链接到某些 CRT 库。程序的真正入口点是 /usr/lib/crt1.o 中定义的
_start()
函数。该函数调用一些 libc 函数,例如 __libc_start_main()。因此你仍然需要 libc 库...你可以不用 libc,但这很棘手。您需要重命名入口点
_start()
,或指示链接器从main()
开始。而且您还需要一些内联汇编来在程序完成时发出_exit()
系统调用,否则程序就会崩溃。当然,使用 ld 命令显式进行链接,而不是通过 gcc 前端。On Linux, any C program is statically linked to some CRT libraries. The true entry point of the program is the
_start()
function defined in /usr/lib/crt1.o. This function calls some libc functions like__libc_start_main()
. Thus you still need the libc library...You could do without libc, but it's tricky. You would need to rename your entry point
_start()
, or instruct the linker to start atmain()
. And you would also need some inline assembly to issue the_exit()
system call when the program is done, otherwise it would just crash. And of course, do the link explicitly with theld
command instead of through thegcc
frontend.