
Static and Dynamic Linking of C Runtime Libraries with VS2010
Contents
Linking Types
A C or C++ program compiled on Windows almost invariably uses the C Runtime Libary (CRT). This set of functions comes with your default Windows installation and provides some of the most basic operations, read this page for details. Now, remember that the last step of creating an EXE is called linking — the process that combines one or more compiled objects and combines them into a single executable.This post describes how to change your CRT linking method to control the size of your EXE file. There are two ways to link an external library such as a DLL.
- Static linking: All library routines used in the program are copied into the final EXE file. This means there is no dependency on some file existing at run-time.
- Dynamic linking: Both the name of a shareable library and the functions you use from that library are placed in the EXE file. When the executable is loaded, the operating system needs to do some extra work to locate this library and map it into your program’s virtual memory.
There is actually a third, “super-dynamic” way of loading DLL’s : calling a loadLibrary() function in your code. This means that you can load different libraries depending on the way your code flows. We won’t discuss that here, because the linker is oblivious to this method.
Dynamic linking has several advantages, some prominent ones being that your EXE becomes smaller, and that several programs can share the code of one external library so it only has to be loaded into memory once.
I will demonstrate how to change your linking type with the use of CL.EXE. This is the Visual Studio 2010 command-line compiler. It is normally called by the IDE, but it can be used from the command prompt if you want to see what’s going on. Open your Visual Studio Command Prompt to use it. The command-line options for CL.exe can be found here. For the MSDN page on the different C run-time libraries available in Windows check out this page.
Let’s look at this example program test.c
.
#includeint main() { printf("Foo!"); return 0; }
Static CRT linking: /MT
Compile this program using the following syntax:
cl /MT test.c
The /MT
option enforces static linking, and it is the default behavior. From the MSDN page:
Causes your application to use the multithread, static version of the run-time library. Defines _MT and causes the compiler to place the library name LIBCMT.lib into the .obj file so that the linker will use LIBCMT.lib to resolve external symbols.
The result program test.exe
will be 44kb in size. If we inspect the executable using PE Tools, our expectations are confirmed that the CRT has been incorporated inside the executable. The Import Table shows it only imports functions from SHELL32.dll.
Dynamic CRT linking: /MD
Let’s compile our program using that option:
cl /MD test.c
The /MD
option enforces dynamic linking. Microsoft has the following to say on this:
Causes your application to use the multithread- and DLL-specific version of the run-time library. Defines _MT and _DLL and causes the compiler to place the library name MSVCRT.lib into the .obj file.
Applications compiled with this option are statically linked to MSVCRT.lib. This library provides a layer of code that allows the linker to resolve external references. The actual working code is contained in MSVCR100.DLL, which must be available at run time to applications linked with MSVCRT.lib.
This adds an entry to MSVCR100.DLL to the executables Import Table. This DLL file will be looked up by the Windows loader when the executable is launched.
Using this external library has an effect on the file size: test.exe
is only 6kb in size. Upon inspection it turns out that the executable now imports both SHELL32.dll and MSVCR100.dll.
Changing the Linking Method in Visual Studio 2010
Go to your project’s Properties -> Configuration Properties -> C/C++ -> Code Generation.
Change ‘Runtime library’ to your desired value. Click OK.
Helpful, thank you. I was looking for how to change from dynamic to static linking in Visual Studio.
As a novice, these linker issues are making me bash my head in. Thank you very much for this explanation.
On my VS2010, it seemed like /MD was the default behavior, but I’m not sure…
I meant to say that it is the default behavior of the cl.exe binary. So if you omit /MD or /MT it will assume /MT. It makes sense that VS2010 would use /MD as the default, so you are probably correct there.
what the fuck&549f1a88660bd127d0ce2499d228dc42_NX
what the fuck&4301dce8d6147bd39a2d90d22e621ee2_NX