views:

373

answers:

8

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. 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?

I know it depends on the compiler and OS, but I need either a general answer or particular examples. TIA.

+1  A: 

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.

Andrey
CRT can be statically linked with program
Abyx
@Andrey. Is it the option in visual studio which says runtime library and you can set it to MT MD MTd etc?
Armen Tsirunyan
@Andrey. And also, if you specify in what cases does the program require C++ redist, I'll accpept your answer
Armen Tsirunyan
@Armen Tsirunyan redist's are always required (linked or standalone) regardless of what classes do you use. every C++ app need them.
Andrey
@Andrey: What DO the C++ redists contain?
Armen Tsirunyan
@Armen Tsirunyan: at least all the parts of C++ standard library that aren't in common with C and aren't template, and all the support code for some C++ magic (e.g. exceptions, RTTI, ...).
Matteo Italia
@Matteo: Thanks! I get it now.
Armen Tsirunyan
And the C runtime libraries come with windows by default, is that correct?
Armen Tsirunyan
Yes and no. There are several CRTs used by the various versions of VC++. By default Windows bundles a CRT (msvcrt.dll IIRC) that is used by all the Windows applications. Also VC++6 (again, IIRC) uses it. The problem is that newer versions of VC++ use slightly different CRTs (with bugfixes, new features, etc), so they cannot use that dll (which, BTW, varies with the Windows versions), so each VC++ newer than 6 use their private CRT (which from some version is not intended anymore to be private to the application but it's a redist *packet*, to make deploying patches easier).
Matteo Italia
*But*, the DDK at some point provided some .LIBs that can be used to use msvcrt.dll for what isn't changed since VC++6, but statically linking the newer features. Notice that AFAIK this is completely undocumented, so in general it shouldn't be used. IIRC MinGW too uses this approach by default.
Matteo Italia
+6  A: 

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.

paxdiablo
-1 for "The second makes no use of runtime libraries". It does in general depend on the runtime library for process startup and termination. In Windows the runtime lib provides the program entry point and after `main` it calls `ExitProcess` (if I recall the name correctly).
Alf P. Steinbach
@Alf, did you not see the text following that: `"other than the C startup code ..."`? It may also be a matter of definition. The startup and termination code _may_ be in the CRT but I've seen plenty of situations where it's in a standalone `start.o` and nothing to do with the standard library. I'll clarify.
paxdiablo
It is indeed arguable whether the init/term code can be considered part of the RTL. Physically, it's linked in, so yes it is. But logically, it's not exposing application-oriented callable resources or data, so no it's not. Given that the answer clearly accounts for this, -1 is definitely uncalled-for.
Stabledog
@paxdiablo: Yeah, but I was concerned with termination, which in general cannot be optimized away since it's about OS requirements, not C requirements. It may additionally include handling of uncaught (OS and/or C++) exception. Now that you've added wording about that, I've removed the downvote. Cheers,
Alf P. Steinbach
No probs, @Alf. I'm happy for critiques since it does, after all, allow me to make my answers better.
paxdiablo
+1  A: 

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.

Andy Johnson
+7  A: 

For Windows applications you can use the Dependency Walker to see all dependencies.

Sebastian N.
http://www.dependencywalker.com/ - something of a life saver when it comes to checking dependencies.
Adam Bowen
Linux equivalent would be `ldd`: a command which list the libraries you depend upon (and where it finds them). There is also `nm` to get the list of symbols referenced, those marked with `U` (undefined) are those you'll go and pick in another DLL.
Matthieu M.
+1  A: 

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).

RIPUNJAY TRIPATHI
+2  A: 

Compile them with GCC, and get executable named 'hi', in console write:

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)
Green Code
I wonder why it uses libjpeg.so
hiena
@hiena: Given that the program is "tifftest", I'd suspect it's a test program for image formats.
David Thornley
Weird indeed. On my box, C++ programs are always liked with linux-gate, libstdc++, libm, libgcc_s, libc and ld-linux. C programs are only liked to linux-gate, libc and ld-linux. No libtiff, libjpeg or libz, unless explicitly requested.
Edgar Bonet
That was just an example, the things which are always needed are libc and ld-linux.
Green Code
@Edgar: Thanks for your very great comment, appreciated.
Green Code
+1  A: 

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 at 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. And of course, do the link explicitly with the ld command instead of through the gcc frontend.

Edgar Bonet
+1  A: 

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 like HeapCreate and ExitProcess. 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 and DecodePointer. 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.

AshleysBrain