在Windows系统下,MSVCRT是否类似于*nix系统下的glibc(libc)?

31

我经常遇到一些Windows程序将MSVCRT(或其更当前身份)与程序可执行文件捆绑在一起。在典型的PC上,我会发现许多相同的.dll文件。我的理解是,MSVCRT是C运行时库,类似于*nix下的glibc/libc.so。

为什么Windows程序必须携带它们的C库,而不能共享系统范围内的libc?


更新:感谢Shog9的指引,我开始阅读有关SxS的内容,这进一步开启了我对DLL链接问题(DLL Hell)的认识 - 此链接 是介绍该问题的一个有用的入门...

4个回答

21

[我是微软公司Native SxS技术的现任维护者]

新版本的MSVCRT会随着Visual Studio的新版本发布,并反映C++工具集的变化。为了让使用较早版本Windows的计算机也能够运行在VS特定版本之后编译的程序(如在Windows XP上编译的VS 2008项目),MSVCRT可以作为可再发行组件进行安装。

CRT安装将库文件放置在%windir%\winsxs\目录下,这是全局系统位置,需要管理员权限才能进行安装。

由于一些程序不想要搭配安装器发布,或者不希望用户需要对计算机有管理员权限才能运行他们的安装程序,因此他们直接将CRT打包到应用程序的同一目录中以供私人使用。所以在典型的计算机上,您会发现许多程序都选择了这种解决方案。


1
似乎微软的解决方案将编译器和C运行时库版本捆绑在一起。 - Baiyan Huang
我认为 MSVCRT 现在只作为 Windows 的一部分发布,而新版 VC 的运行时具有新的 DLL 名称? - SamB

17

在Windows中并没有真正的“系统范围libc”。

在*nix中,通常有一个编译器、一个连接器,以及一个明确定义的目标文件格式、调用约定和名称混淆规范。这些内容通常随操作系统提供。编译器的半特殊状态(加上跨不同*nix的可移植性强调)意味着某些东西可以被期望存在,并且以这种方式命名或版本化,以便程序可以轻松地找到并使用它。

在Windows中,情况更加分散。编译器不随操作系统提供,因此人们需要自己获取。每个编译器都提供其自己的CRT,其中可能有与MSVCRT中不同的函数。对于调用约定或库中名称应如何出现,也没有一个唯一的规范,因此具有不同做法的不同编译器可能会遇到在库中找不到函数的问题。

顺便提一下,名称应该是一个提示;MSVCRT简称为“MicroSoft Visual C++ RunTime”。它并不像kernel32那样是一个真正的“系统范围”库——它只是由MS编译器使用的运行时库,他们在构建Windows时使用了它。其他编译器可以概念性地链接到它,但(1)可能会涉及到许可问题;(2)编译器将把他们的代码与MS的代码绑定在一起——这意味着(2a)他们不再有任何方法添加运行时或修复错误,除非希望MS来修复它们;(2b)如果MS决定改变RTL中的内容(他们可以随意进行,而且可能在每个VC++新版本中都会这样做),或者更改名称的方式,那些其他程序可能会出现问题。


13

简短回答?因为在 SxS 之前,MSVCRT 并没有可靠的版本控制!试想一下,如果程序是针对 libc 5 编译和测试的,而悄然地开始使用 libc 6,那将会带来怎样的疯狂局面?这就是多年来 Windows 所处的情况。我们中的大多数人很快就再也不愿意相信 MS 能够将破坏性的变更排除出一个版本。


5
SxS不能保证你会使用与编译时相同的版本 :( 默认情况下,它遵循策略,而默认策略是自动升级。 - Greg Domjan

3
程序链接到特定版本的运行时,但并不保证目标机器上存在所需版本。此外,匹配使用的版本曾经是有问题的。
在Windows世界中,期望用户去查找和安装单独的库来使用应用程序是非常不礼貌的。您需要确保将主机系统中不包含的任何依赖项都包含在您的应用程序中。
在Linux世界中,这并不总是那么简单,因为主机系统可能看起来有很大的变化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接