-
Implementation of the C Standard.
-
Each one implements the C Standard optimized for the target platform.
Most Popular Implementations
-
BSD libc
-
Various implementations distributed with BSD-derived operating systems.
-
-
GNU C Library (glibc)
-
Used in GNU Hurd, GNU/kFreeBSD, and most Linux distributions.
-
-
Microsoft C run-time library (MSVCRT / UCRT).
-
Part of Microsoft Visual C++. There are two versions of the library: the formerly-redistributable (until Visual Studio 2013) MSVCRT which is not compliant to the C99 standard, and the newer UCRT (Universal C Run Time) shipped as part of Windows 10 and 11 which is C99-compliant.
-
-
dietlibc
-
An alternative small implementation of the C standard library (MMU-less)
-
-
ÎĽClibc
-
AC standard library for embedded ÎĽClinux systems (MMU-less)
-
uclibc-ng
-
An embedded C library, fork of ÎĽClibc, still maintained, with memory management unit (MMU) support
-
-
-
Newlib
-
A C standard library for embedded systems (MMU-less)6 and used in the Cygwin GNU distribution for Windows
-
-
klibc
-
Primarily for booting Linux systems
-
-
musl
-
Another lightweight C standard library implementation for Linux systems
-
-
Bionic
-
Originally developed by Google for the Android embedded system operating system, derived from BSD libc
-
-
picolibc
-
Developed by Keith Packard, targeting small embedded systems with limited RAM, based on code from Newlib and AVR Libc.
-
What am I using?
-
If you just wrote that code and compiled it normally with a mainstream compiler, here’s what you can expect:
-
Linux (gcc or clang) :
-
uses glibc’s by default.
gcc main.c -o main # links with glibc automatically -
-
macOS (clang)
-
Uses Apple’s libc (based on FreeBSD’s) implementation.
-
-
Windows (MSVC)
-
Uses Microsoft’s Universal CRT (UCRT) implementation.
-
-
-
It’s always the platform’s standard C library implementation, automatically linked when you compile with
gcc,clang, orMSVC.
Finding out which implementation was used
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int *nums = malloc(sizeof(int) * 5);
memset(nums, 0, sizeof(int) * 5);
return 0;
}
-
Just looking at this code above is not possible to know which implementation was used.
-
To find out, you can check:
-
Which C library your program links to
-
ldd ./a.outshows dynamic libraries. If you seelibc.so.6you’re using glibc (or its symlink). If you seemuslorlibc.sofrom another vendor that tells you the vendor.
-
-
Which
memsetsymbol is present in that libc-
objdump -T /lib/x86_64-linux-gnu/libc.so.6 | grep memsetornm -D /lib/x86_64-linux-gnu/libc.so.6 | grep memset -
This shows whether
memsetis provided by that library.
-
-
Does your binary actually call the libc function or was it optimized/ inlined?
-
Inspect the binary symbols:
readelf -Ws ./a.out | grep memset-
If you see an
UNDentry formemsetit’s an external call.
-
-
Disassemble the binary:
objdump -d ./a.out | lessand search forcall.*memset.-
If there is no call, compile-time optimization may have inlined a loop or emitted an intrinsic.
-
-
To see compiler codegen: compile to assembly:
-
gcc -O2 test.c -S -o test.s(optimized) andgcc -O0 test.c -S -o test_O0.s(unoptimized). Inspect for acalltomemsetor a loop/rep stosbsequence.
-
-
-