The Microsoft C Runtime Library (CRT) provides the foundational routines that power nearly every C and C++ program compiled with MSVC. From basic I/O and string manipulation to math, memory allocation, time functions, and process control, the CRT abstracts operating-system internals into a portable, well-defined API. Understanding which CRT variant your project links against is critical for both correctness and deployment — the wrong choice can cause DLL conflicts, state isolation bugs, or redistributable packaging errors.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/MicrosoftDocs/cpp-docs/llms.txt
Use this file to discover all available pages before exploring further.
What the CRT Provides
The CRT is organized into functional categories, each mapping to a well-known area of the C standard library or Windows-specific extensions:I/O & File Handling
printf, scanf, fopen, fread, fwrite, fclose, fseek, ftell — complete ANSI C stream I/O plus Windows extensions.String Manipulation
strcpy_s, strcat_s, strlen, strtok_s, sprintf_s, sscanf_s — safe and unsafe variants for byte and wide strings.Memory Allocation
malloc, calloc, realloc, free, _aligned_malloc, memcpy_s, memmove_s — heap management and buffer operations.Math & Floating-Point
sqrt, pow, sin, cos, floor, ceil, fabs, fmod — full C99 math library with floating-point support.Time Management
time, clock, localtime_s, gmtime_s, mktime, difftime, strftime — POSIX-compatible time functions.Process & Environment
exit, atexit, _exit, system, getenv, _putenv, abort — process lifecycle and environment variable access.CRT Variants and Compiler Options
When you build with MSVC, the linker option you choose determines which CRT library your binary links against. This is one of the most important build decisions you will make.- Release Variants
- Debug Variants
| Option | Library | Type | Characteristics |
|---|---|---|---|
/MD | msvcrt.lib → ucrtbase.dll | Dynamic (DLL) | Shared CRT state across DLLs; requires Visual C++ Redistributable |
/MT | libcmt.lib | Static | CRT compiled into your binary; no external DLL dependency |
Static vs Dynamic Linking Trade-offs
Why prefer /MD (dynamic linking)?
Why prefer /MD (dynamic linking)?
Dynamic linking (
/MD) means all DLLs and the main executable share a single CRT instance. This allows heap memory allocated in one module to be freed in another — a requirement if you pass std::string, std::vector, or raw malloc pointers across DLL boundaries. It also means Windows Update can service the CRT independently, improving security.When is /MT (static linking) appropriate?
When is /MT (static linking) appropriate?
Static linking (
/MT) produces a self-contained binary with no dependency on redistributable DLLs. This is useful for small command-line utilities or plugins where you control the entire binary. However, every module (EXE + DLLs) gets its own CRT heap — passing heap-allocated pointers across module boundaries causes undefined behavior.All modules in a process must use the same CRT variant. Mixing
/MD and /MT within a process is a common source of hard-to-diagnose crashes and assertion failures.Universal CRT (UCRT) vs Legacy CRT
Starting with Visual Studio 2015, the CRT was split into two components:Universal CRT (UCRT)
ucrtbase.dll — contains all standard C99 functions (stdio, math, string, etc.). The UCRT ships as part of Windows 10 and later, and is available on older Windows via the Windows SDK redistributable. It is now a stable, OS-versioned component.VC Runtime (vcruntime)
vcruntime140.dll — contains compiler-specific support: exception handling (__try/__except), C++ type information, security cookies, and certain intrinsics. This component is version-specific and ships with the Visual C++ Redistributable.Legacy CRT (pre-VS 2015)
Before Visual Studio 2015,msvcr120.dll, msvcr110.dll, etc. bundled the C runtime and VC runtime together. These versions are version-specific and require matching redistributables. They are still supported but no longer receive new features.
CRT Initialization and Global State
The UCRT maintains global state (locale, heap, stdio buffers) at the process level when using
/MD. When using /MT, each statically linked module has its own isolated CRT state. This means strtok positions, file handles opened in one module, and locale settings are not shared across static CRT boundaries.