简体   繁体   English

C ++程序需要运行什么?

[英]What does a C++ program require to run?

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;
}
  1. Windows: The first example, naturally, requires some system .dll's for the console. Windows:第一个例子,当然需要一些系统.dll用于控制台。 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? 那么,运行时库实际上做了什么?
  2. Linux: No idea, can you enlighten me? Linux:不知道,你能开导我吗?

I know it depends on the compiler and OS, but I need either a general answer or particular examples. 我知道这取决于编译器和操作系统,但我需要一般答案或特定的例子。 TIA. TIA。

As a general answer, the first will require the C++ runtime libraries (the stuff you need to support the standard library calls). 作为一般答案,第一个将需要C ++运行时库(您需要支持标准库调用的东西)。 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. 它将使用C启动和终止代码(初始化和拆除C环境),但它是关于这些是否被视为运行时库的一部分的讨论点。 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和Linux都是如此。

对于Windows应用程序,您可以使用Dependency Walker查看所有依赖项。

The first program performs stream I/O, which means it has to interact with resources (console, gui) managed by the OS. 第一个程序执行流I / O,这意味着它必须与OS管理的资源(控制台,gui)进行交互。 So, ultimately, the OS has to be invoked via an API implemented in a system dll. 因此,最终,必须通过系统dll中实现的API调用操作系统。

On windows the second program requires no libraries. 在Windows上,第二个程序不需要库。 I'm fairly sure the same is true on Linux. 我很确定在Linux上也是如此。

Compile them with GCC, and get executable named 'hi', in console write: 用GCC编译它们,并在控制台写入中获得名为'hi'的可执行文件:

ldd hi

will give you the shared objects(dynamic libraries) which are connected to your program. 将为您提供连接到您的程序的共享对象(动态库)。

Just for quick answer here is an output: 只是为了快速回答这里输出:

ldd tifftest
  libtiff.so.3 => /usr/lib/libtiff.so.3 (0x4001d000)
  libc.so.6 => /lib/libc.so.6 (0x40060000)
  libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x40155000)
  libz.so.1 => /usr/lib/libz.so.1 (0x40174000)
  /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)

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. 首先,您需要一台具有兼容CPU的计算机,该计算机可与编译器输出的目标机器配合使用。 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. 您可能认为这是显而易见的,但假设代码编译为x86机器代码,它将不会在使用不同指令的Alpha CPU上运行。 Alternatively, if you compile to x64 machine code, it won't run on an x86-only CPU. 或者,如果编译为x64机器代码,则它不会在仅限x86的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. 因此,运行C ++程序需要正确的硬件,这与基于虚拟机的语言(如Java)相反,后者将其抽象出来。

  • 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++. 我不是移植程序的专家,但我认为不可能在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. 例如,即使你的第二个例子编译到Windows,在实际调用main()函数之前和之后的幕后都会有很多运行时库代码。 This will do things like prepare the heap and initialise the CRT library. 这将执行诸如准备堆和初始化CRT库之类的操作。 The CRT for Windows is implemented via the Windows API. Windows的CRT是通过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. 您可以静态链接库,因此不需要CRT DLL,但程序中的代码仍然会调用Windows API,因此仍然依赖于平台。 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 like HeapCreate and ExitProcess . 作为一个实验,我使用Visual Studio在Windows上使用静态链接编译了一个空程序,并且根据Dependency Walker,它仍然为HeapCreateExitProcess等函数引用了KERNEL32.DLL。 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). 所以'empty'程序仍然会为你做一大堆操作系统的东西,为做一些有用的事情做准备(无论你的程序是否有用)。

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 and DecodePointer . 另请注意,可能存在最低操作系统版本:由于调用EncodePointerDecodePointer ,Visual Studio 2010甚至需要Windows XP SP2或更高版本才能使用空程序。 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. 您可能认为它什么都不做,但如上所示,在调用main()之前,整个OS加载初始化调用是由程序库完成的。 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. 因此,简而言之,即使使用静态链接运行空C ++程序,您也需要正确的CPU,操作系统,运行可执行文件的权限以及完成程序的内存/处理时间。 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. 与Java或.NET等VM技术相比,这些要求可能只会减少到正确的虚拟机,必要的权限以及运行程序所需的内存/ CPU时间。 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. 这可能不像听起来那么简单:您可能需要正确版本的虚拟机,例如.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. 这会使您的分发过程复杂化,因为为机器更新整个JVM或.NET框架可能是一个耗时的过程,需要管理员权限和Internet连接。 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". 在一些狭隘的情况下,这可能是一个交易破坏者,因为在极少数情况下,它可能更容易说“它将在任何x86兼容的Windows操作系统上运行自XP”,而不是“任何具有最新虚拟机的机器昨天才发布的机器“。 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; 但是,对于大多数用途,虚拟机允许您(理论上)忘记CPU和操作系统这一事实使得程序的分发更容易; 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. 使用C ++,您需要至少为要支持的平台和CPU的每个组合编译单独的可执行文件,而不管您正在使用的库的其他要求。

C programs on Windows require CRT libraries that come with Windows. Windows上的C程序需要Windows附带的CRT库。 C++ sometimes require so called "C++ redistributable". C ++有时需要所谓的“C ++可再发行”。 They can be embedded in app via linking but this will make EXE bigger. 它们可以通过链接嵌入到app中,但这会使EXE更大。

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. 但总的来说,它需要的是明确定义的地址空间(在主存储器中),其属性和CPU时间。 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"). 除非有一些荒谬的冲突,否则你的程序会得到这个(这就是为什么我猜Chubsdad评论“你需要运气”)。

OS scheduling, CPU asking to fetch instructions/data from memory and then the executing it... all forms a "machine" that executes your program. 操作系统调度,CPU要求从内存中获取指令/数据然后执行它......所有这些都构成了执行程序的“机器”。

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). 找到入口点(或程序中要执行的第一个点)就是在编译时(例如主函数)或者使用某些系统调用(如Unix)/ CreateProcess(使用某些系统调用)加载程序时所做的一切。 )(在Windows中)。

On Linux, any C program is statically linked to some CRT libraries. 在Linux上,任何C程序都静态链接到某些CRT库。 The true entry point of the program is the _start() function defined in /usr/lib/crt1.o. 该程序的真正入口点是/usr/lib/crt1.o中定义的_start()函数。 This function calls some libc functions like __libc_start_main() . 此函数调用一些libc函数,如__libc_start_main() Thus you still need the libc library... 因此你仍然需要libc库......

You could do without libc, but it's tricky. 你可以没有libc,但它很棘手。 You would need to rename your entry point _start() , or instruct the linker to start at main() . 您需要重命名入口点_start() ,或者指示链接器从main()开始。 And you would also need some inline assembly to issue the _exit() system call when the program is done, otherwise it would just crash. 并且你还需要一些内联汇编来在程序完成时发出_exit()系统调用,否则它就会崩溃。 And of course, do the link explicitly with the ld command instead of through the gcc frontend. 当然,使用ld命令显式链接而不是通过gcc前端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM