不同平台的C/C++标准库

Posted lyf5231

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不同平台的C/C++标准库相关的知识,希望对你有一定的参考价值。

1. C/C++标准

C/C++所涉及到的参与者,根据角色的不同,可以分为以下3类:

  1. C/C++标准起草者,主要在ISO标准组织( International Organization for Standardization),他们负责对应C/C++标准相关的制定,每隔几年制定一个新的标准,这也就是C99, C11, C++03, C++11, C++14,C++20的由来。

如上图所示,每一个阶段的标准,都大致对应两部分内容:

  • 语言本身的新增功能
  • 标准库新增的功能,标准库一般是我们学习编程的起点,无论是std::cout()或者printf()函数都是标准库中的函数,标准库为我们提供了丰富的操作系统底层系统软、硬件系统相关的函数接口。

例如,

在C标准中,main函数的定义如下,它规定了main()函数应该是什么样的。

标准C库在math.h中定义了fmin函数,它定义了标准库函数的签名,但是标准就只有标准,没有实现,具体的实现由另外一波人完成

  1. C/C++编译器及标准库开发者

C/C++的标准库的开发者主要是利用语言和库相关的标准文件,将它们翻译成C/C++代码。由于C/C++是偏底层的高级语言,因此它们的标准库中牵扯到很多和操作系统相关的接口,例如read/write,内存分配、线程调度等,这些操作都牵扯到系统调用(system call),因此不同的操作系统应该会有不同的标准库的实现?

如图1所示,GCC,MSVC,CLANG是目前最主流的C/C++编译器,编译器是一组程序(这里包含链接等程序),它们的主要作用是将C/C++源代码翻译成可以执行的机器字节码(可执行程序)。因此,编译器的开发者们一般会完成C/C++标准中新增语言本身部分的开发支持,同时还会完成标准库之一的一个实现。

  1. C/C++程序员

程序员们在特定的操作系统上(MAC、Windows、Linux等),利用特定的IDE(Xcode、Clion、Visual Studio等)或者文本编辑器(VSCode、Sublime等)完成C/C++源代码的编写,然后利用特定的编译器对源代码进行编译,链接对应的标准库,生成可执行程序,完成特定的软件功能。

2. 各种各样的C/C++标准库

基于以上的分析,下面对常用的C/C++标准库进行介绍。

2.1 GNU/Linux实现

在GNU/Linux上,使用最广泛的C/C++编译器为GCC。

The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, Go, and D, as well as libraries for these languages (libstdc++,…). GCC was originally written as the compiler for the GNU operating system.

而(区分Collection和Compiler)

  • gcc,GNU C Compiler,是对应的C编译器;
  • g++,GNU C++ Compiler,是对应的C++编译器。

The GNU C library,也就是Glibc,是Linux中使用最广泛的C标准库。

The GNU C Library project provides the core libraries for the GNU system and GNU/Linux systems, as well as many other systems that use Linux as the kernel. These libraries provide critical APIs including ISO C11, POSIX.1-2008, BSD, OS-specific APIs and more. These APIs include such foundational facilities as open, read, write, malloc, printf, getaddrinfo, dlopen, pthread_create, crypt, login, exit and more.

而GNU/linux上对应的C++标准库为libstdc++ (In general all commonly available linux distributions will use libstdc++ by default.)。

2.2 MAC实现

The LLVM project started in 2000 at the University of Illinois at Urbana–Champaign, under the direction of Vikram Adve and Chris Lattner. LLVM was originally developed as a research infrastructure to investigate dynamic compilation techniques for static and dynamic programming languages. LLVM was released under the University of Illinois/NCSA Open Source License,[3] a permissive free software licence. In 2005, Apple Inc. hired Lattner and formed a team to work on the LLVM system for various uses within Apple’s development systems.[16] LLVM has been an integral part of Apple’s Xcode development tools for macOS and iOS since Xcode 4.[17]

In 2006, Lattner started working on a new project called Clang. The combination of Clang front-end and LLVM back-end is called Clang/LLVM or simply Clang.

以上说明是LLVM项目和Apple之间的渊源,而Clang作为C系语言(C/C++/Objective C/C++)编译系统的前端,将源代码编译成LLVM所需的字节码,而后端LLVM将这些字节码转换为可执行程序。

The LLVM project has multiple components. The core of the project is itself called “LLVM”. This contains all of the tools, libraries, and header files needed to process intermediate representations and converts it into object files. Tools include an assembler, disassembler, bitcode analyzer, and bitcode optimizer. It also contains basic regression tests.

C-like languages use the Clang front end. This component compiles C, C++, Objective C, and Objective C++ code into LLVM bitcode – and from there into object files, using LLVM.

Other components include: the libc++ C++ standard library, the LLD linker, and more.

从上面的介绍中可以看出LLVM项目中涉及到Clang前端,LLVM后端,LLD链接器,还有个名字叫libc++的C++标准库。OS X 在Mavericks版本(version 10.9)之前,使用的C++库也是libstdc++ ,而在Mavericks版本之后,实现了自己的libc++标准库,号称是专门为Clang特别重写的。

上面专门提到了标准C++的库,但是没有提到标准C库?

This is a proposal to start llvm-libc, an implementation of the C standard library targeting C17 and above, as part of the LLVM project. llvm-libc will also provide platform specific extensions as relevant. For example, on Linux it also provides pthreads, librt and other POSIX extension libraries.

llvm-libc是目前正在进行的一个标准C库相关的工作,作为LLVM项目的一部分,不过目前貌似还实现的不完整

The libc is not complete. If you need a fully functioning C library right now, you should continue to use your standard system libraries.

目前LLVM还未提供成熟的标准C库,言下之意,应该是可以使用大部分其他的标准实现。

Clang supports a wide variety of C standard library implementations.

当然,Clang也可以用-stdlib=libstdc++ 来指定使用 libstdc++标准库。

2.3 Windows实现

The C runtime Library (CRT) is the part of the C++ Standard Library that incorporates the ISO C standard library.

Starting in Visual Studio 2015, the CRT has been refactored into new binaries. The Universal CRT (UCRT) contains the functions and globals exported by the standard C99 CRT library. The UCRT is now a Windows component, and ships as part of Windows 10 and later versions. The static library, DLL import library, and header files for the UCRT are now found in the Windows SDK. When you install Visual C++, Visual Studio setup installs the subset of the Windows SDK required to use the UCRT. You can use the UCRT on any version of Windows supported by Visual Studio 2015 and later versions. You can redistribute it using vcredist for supported versions of Windows other than Windows 10 or later.

Windows的C标准库为CRT(C runtime Library),从VS2015以后,CRT重写,改名为UCRT(UCRT相当于Linux上的glibc),之前为MSVCRT (Microsoft Visual C++ Runtime,后面在介绍Mingw时的编译例子会详细介绍) 。WIN10之后,UCRT已经是操作系统的一部分,对应的静态库,DLL,头文件等等都可以在Windows SDK中找到。

如上图所示,Windows上的标准C库ucrt.lib在ucrtbase.dll中。

The vcruntime library contains Visual C++ CRT implementation-specific code, such as exception handling and debugging support, runtime checks and type information, implementation details and certain extended library functions. The vcruntime library version needs to match the version of the compiler you’re using.

除了ucrt.lib,vcruntime库包含了Visual C++ CRT特定实现的一些东西,例如exception handling and debugging support, runtime checks and type information, implementation details and certain extended library functions等。

上图中,vcruntime.lib位于vcruntime.dll中。

From a historical perspective, “STL” originally referred to the Standard Template Library written by Alexander Stepanov. Parts of that library were standardized in the C++ Standard Library, along with the ISO C runtime library, parts of the Boost library, and other functionality. Sometimes “STL” is used to refer to the containers and algorithms parts of the C++ Standard Library adapted from Stepanov’s STL. In this documentation, Standard Template Library (STL) refers to the C++ Standard Library as a whole.

而,Windows对应的C++标准库,微软把它也叫做"STL"(MSVC’s implementation of the C++ Standard Library.)。具体源码可以见[github](microsoft/STL: MSVC’s implementation of the C++ Standard Library. (github.com))。

C++标准库(动态链接)msvcprt.lib位于msvcp.dll,当你在代码中包含了C++标准库中的头文件时,编译器会自动将msvcp.dll链接到你的代码中。

在Visual Studio中创建了一段测试代码,包含了C++标准库中的头文件,

#pragma warning(disable: 4018)

#pragma warning(disable:4786)
#include <iostream>
#include <string>
#include <map>
using namespace std;

在debug下,对应程序链接的动态库包括:

  1. UCRT,标准C库,对应ucrtbased.dll(debug);
  2. vcruntime库,对应VCRUNTIME140D.DLL,VCRUNTIME140_1D.DLL;
  3. STL,标准C++库,对应MSVCP140D.DLL。

在release模式下,对应程序链接的动态库和debug下类似,只不过对应release下的DLL。

3. 其他一些标准库及周边

3.1 Cygwin

Cygwin is a Linux-like environment for Windows. It consists of a DLL (cygwin1.dll), which acts as an emulation layer providing substantial POSIX (Portable Operating System Interface) system call functionality, and a collection of tools, which provide a Linux look and feel. The Cygwin DLL works with all x86 and AMD64 versions of Windows NT since Windows XP SP3. The API follows the Single Unix Specification as much as possible, and then Linux practice. The major differences between Cygwin and Linux is the C library (newlib instead of glibc).

With Cygwin installed, users have access to many standard UNIX utilities. They can be used from one of the provided shells such as *bash* or from the Windows Command Prompt. Additionally, programmers may write Win32 console or GUI applications that make use of the standard Microsoft Win32 API and/or the Cygwin API. As a result, it is possible to easily port many significant UNIX programs without the need for extensive changes to the source code. This includes configuring and building most of the available GNU software (including the development tools included with the Cygwin distribution).

Cygwin是Windows上运行的一个类linux环境,主要包括

  1. cygwin1.dll,它提供POSIX的抽象层,因此很多Linux/Unix的程序不需要大的修改,就可以依靠链接cygwin1.dll,轻松完成到Windows上的移植;
  2. 其他的一些GNU tools, BSD tools, an X server and a full set of X applications;
  3. Cygwin的C标准库为newlib,而不是glibc
  4. Cygwin项目中,几乎包含了所有的常用linux软件以及常用库,包括eigen3,boost,libstdc++6等。

上图为Cygwin中newlib的源码,其中数学库libm和其他libc的源码是分开的。

3.2 MinGW

MinGW (“Minimalist GNU for Windows”), formerly mingw32, is a free and open source software development environment to create Microsoft Windows applications. MinGW includes a port of the GNU Compiler Collection (GCC), GNU Binutils for Windows (assembler, linker, archive manager), a set of freely distributable Windows specific header files and static import libraries which enable the use of the Windows API, a Windows native build of the GNU Project’s GNU Debugger, and miscellaneous utilities.

MinGW 是GNU的一些开发工具,例如GCC、GNU 汇编、链接等程序在Windows上的移植,提供了一套Windows上的开发环境。最初的MinGW指的是MinGW32。

Mingw-w64 is an advancement of the original mingw.org project, created to support the GCC compiler on Windows systems. It has forked it in 2007 in order to provide support for 64 bits and new APIs. It has since then gained widespread use and distribution.

2007年以后,为了支持64位系统和新的API,衍生出了Mingw-w64。

  • More than a million lines of headers are provided, not counting generated ones, and regularly expanded to track new Windows APIs.
  • Everything needed for linking and running your code on Windows.
  • Winpthreads, a pthreads library for C++11 threading support and simple integration with existing project.
  • Winstorecompat, a work-in-progress convenience library that eases conformance with the Windows Store.
  • Better-conforming and faster math support compared to VisualStudio’s.

而MinGW的目的是为了开发原生的Windows程序,开发了Winpthreads库,用来支持C++11中的thread相关的功能。

那么,在MinGW环境下编译的原生C++程序和Visual Studio有什么不同?用和Visual Studio中同样的C++测试代码,编译环境选择mingw64,编译器选择mingw64的gcc和g++,

Executing command: "C:\\Program Files\\CMake\\bin\\cmake.EXE" --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=E:\\msys64\\mingw64\\bin\\gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=E:\\msys64\\mingw64\\bin\\g++.exe -Se:/test -Be:/test/build -G Ninja

生成的应用程序所加载的库和原生Visual Studio有很大的不同,如下所示,

  1. 首先是msvcrt.dll,那么什么是msvcrt.dll?

MSVCRT.DLL is the C standard library for the Visual C++ (MSVC) compiler from version 4.2 to 6.0. It provides programs compiled by these versions of MSVC with most of the standard C library functions. These include string manipulation, memory allocation, C-style input/output calls, and others. MSVCP*.DLL is the corresponding C++ library.

msvcrt.dll是MSVC4.2到6.0版本之间的标准C库,而msvcp*.dll是对应的C++标准库(和上文相同)。

With Version 14.0, most of the C/C++ runtime was moved into a new DLL, UCRTBASE.DLL. However, C/C++ programs using UCRTBASE.DLL are forced to link against another new DLL, the VCRuntime. At Version 14.0, this was VCRUNTIME140.DLL.[17] The name has the potential to change at future versions, but has not done so as far as Version 17.0.

This runtime library is used by programs written in Visual C++ and a few other compilers (e.g. MinGW). Some compilers have their own runtime libraries.

MSVC14.0(VS2015)及以后,有了UCRT,就是上文提到的ucrtbase.dll,在链接ucrtbase.dll的同时,也会去链接vcruntime库,也就是上文提到的VCRUNTIME140D.DLL。这个名字未来可能会变,但是在MSVC 17.0,也就是VS2022上目前依然没变。MinGW确实会链接该DLL作为标准C库。

  1. 标准C++库使用的是libstdc++,对应的dll为libstdc+±6.dll。同时链接了libwinpthread-1.dll,对应Winpthreads线程库。

3.3 MSYS2

MSYS2 is a collection of tools and libraries providing you with an easy-to-use environment for building, installing and running native Windows software.

It consists of a command line terminal called mintty, bash, version control systems like git and subversion, tools like tar and awk and even build systems like autotools, all based on a modified version of Cygwin. Despite some of these central parts being based on Cygwin, the main focus of MSYS2 is to provide a build environment for native Windows software and the Cygwin-using parts are kept at a minimum. MSYS2 provides up-to-date native builds for GCC, mingw-w64, CPython, CMake, Meson, OpenSSL, FFmpeg, Rust, Ruby, just to name a few.

  • MSYS2是一些工具和库的集和,用来进行原生Windows软件的开发;

The unixy tools in MSYS2 are directly based on Cygwin, so there is some overlap there. While Cygwin focuses on building Unix software on Windows as is, MSYS2 focuses on building native software built against the Windows APIs.

  • MSYS2中的unix系的工具是基于Cygwin的,但是它没有Cygwin1.dll,而是从Cygwin中fork过来的,并做了修改,编译成了msys-2.0.dll。但是MSYS2和Cygwin的目标是有很大差别的,Cygwin是利用Cygwin1.dll将unix相关软件移植到Windows,而MSYS2是利用Windows原生的API去开发原生的Windows程序。
  • MSYS2提供了大量开发组件,包括GCC,Mingw-w64,CPython,CMake,OpenSSL, FFmpeg, Rust, Ruby等等。

如下图所示,MSYS2提供了多种开发环境,

  • CPU架构支持X86_64,I686(32 bit),aarch64(ARM 64);
  • 编译器支持gcc,clang/llvm;
  • C标准库支持Cygwin,msvcrt,ucrt,C++标准库支持libstdc++,libc++。

如上图所示,MSYS2对应的7种开发环境,对应的bin、lib及头文件等目录依靠名称进行区分。利用pacman安装时,通过包名进行区分,因此在安装环境的时候一定要注意区分,设置好环境变量。

  • 如果不加任何前缀,默认安装的是msys环境,安装在/msys64/usr目录下

  • mingw32环境的包名为,mingw-w64-i686-*,安装在/msys64/mingw32目录下

  • mingw64环境的包名为,mingw-w64-x86_64-*,安装在/msys64/mingw64目录下;

  • ucrt64环境的包名为,mingw-w64-ucrt-x86_64-*,安装在/msys64/ucrt64目录下;

  • clang32环境的包名为,mingw-w64-clang-i686-*,安装在/msys64/clang32目录下;

  • clang64环境的包名为,mingw-w64-clang-x86_64-*,安装在/msys64/clang64目录下;

  • clangarm64环境的包名为,mingw-w64-clang-aarch64-*,安装在/msys64/clangarm64目录下;

3.4 NVIDIA libcu++

libcu++, the NVIDIA C++ Standard Library, is the C++ Standard Library for your entire system. It provides a heterogeneous implementation of the C++ Standard Library that can be used in and between CPU and GPU code.

libcu++是英伟达的C++标准库,包含在英伟达的HPC SDK和CUDA Toolkit中,包含了同时可以在CPU和GPU中运行的C++标准库,这是和其他标准库最大的区别。

3.5 musl libc

[musl](musl libc) is an implementation of the C standard library built on top of the Linux system call API, including interfaces defined in the base language standard, POSIX, and widely agreed-upon extensions. musl is lightweight, fast, simple, free, and strives to be correct in the sense of standards-conformance and safety.

musl is an implementation of the userspace portion of the standard library functionality described in the ISO C and POSIX standards, plus common extensions. It can be used both as the system-wide C library for operating system installations and distributions, and as a tool for building individual application binaries deployable on a wide range of systems compatible with the Linux system calls API.

3.6 Newlib

[Newlib](The Newlib Homepage (sourceware.org)) is a C library intended for use on embedded systems. It is a conglomeration of several library parts, all under free software licenses that make them easily usable on embedded products.

Newlib是为嵌入式设备设计的一款C标准库。对于嵌入式设备,例如MCU等,硬件资源比较紧张,不能用大而全的标准C库,Newlib就是为此而生。Cygwin使用的标准C库就是Newlib。

3.7 uClibc-ng

uClibc-ng is a small C library for developing embedded Linux systems. It is much smaller than the GNU C Library, but nearly all applications supported by glibc also work perfectly with uClibc-ng.

Porting applications from glibc to uClibc-ng typically involves just recompiling the source code. uClibc-ng supports shared libraries and threading. It currently runs on standard Linux and MMU-less (also known as uClinux) systems with support for Aarch64, Alpha, ARC, ARM, AVR32, Blackfin, CRIS, C-Sky, C6X, FR-V, H8/300, HPPA, i386, IA64, KVX, LM32, M68K/Coldfire, Metag, Microblaze, MIPS, MIPS64, NDS32, NIOS2, OpenRISC, PowerPC, RISCV64, Sparc, Sparc64, SuperH, Tile, X86_64 and XTENSA processors. Alpha, FR-V, HPPA, IA64, LM32, NIOS2, Tile and Sparc64 are experimental and need more testing.

uClibc-ng(之前的版本是uClibc)是为了嵌入式Linux系统而开发的一个小的C标准库,轻量化,和glibc兼容性好。

3.8 android Bionic

bionic is Android’s C library, math library, and dynamic linker.

Android的默认标准C库上bionic,Google开发。


建议:在不同的操作系统中使用原生的标准库,否则可能出现兼容性问题。

以上是关于不同平台的C/C++标准库的主要内容,如果未能解决你的问题,请参考以下文章

不同平台的C/C++标准库

Go笔记-标准库的介绍

C语言中时间的函数

GCC是啥编译器?跟vc自带的有啥不同?

使用xmake检测编译器特性支持

浅论“跨平台”