在发布windows软件后,本地运行好好的,但用户那经常会遇到这类报错:
又或者
到底是什么原因呢?
背景知识
要弄懂这个问题,首先要先了解 Microsoft Visual C++ 运行时库 (CRT) 。
Microsoft Visual C++ 运行时库(CRT)是一套由 Microsoft 提供的标准库,包含了一系列用于执行常见操作的函数和数据结构,如输入输出处理、字符串操作、内存分配和数学计算等。这些库提供了基础的程序运行环境,使用Visual C++开发的程序都需要他们。
如果程序所需的运行时库在用户电脑上找不到,而且分发软件时没有打包相应的运行时库,那么用户可能就会弹出前面的报错提示。
VCRuntime
在Visual Studio 2015 之前,CRT 主要指VCRuntime,VCRuntime可以分为几个不同的部分:
-
C 运行时库: 这是 CRT 的核心部分,提供了 C 语言标准库所定义的功能,如
printf()
、malloc()
、fopen()
等。 -
C++ 标准库: 包含 C++ 标准库的实现,涵盖了如 STL 容器(如
vector
、map
等)、算法、字符串类(如std::string
)以及其他标准功能。 -
C++/CLI 运行时库: 用于支持 C++/CLI 语言的特定功能,这是一个为 .NET 框架设计的 C++ 语言变种。
-
并发运行时: 提供了并发和并行编程模型的支持,如任务并行库(TPL)。
-
安全增强的 CRT: 为了防止缓冲区溢出等安全问题,Microsoft 提供了一些增加了安全检查的函数版本,如
strcpy_s()
代替strcpy()
。 -
CRT 的调试版本: 包含了额外的调试信息和检查功能,帮助开发者在开发阶段发现和修复错误。
Visual C++ 运行时库可以以两种方式与应用程序链接:
-
静态链接(/MT 或 /MTd 编译器选项): 运行时库的代码会被编译到应用程序的二进制文件中。这样的应用程序不需要额外的 DLL 文件就可以运行,但会增大最终的可执行文件大小,并且如果运行时库更新,程序也需要重新编译分发。
-
动态链接(/MD 或 /MDd 编译器选项): 应用程序在运行时依赖外部的 DLL 文件,如
msvcrXXX.dll
、msvcpXXX.dll
、vcruntimeXXX.dll
等。动态链接的好处是减小了可执行文件的大小,并且当运行时库更新时,通常不需要重新编译程序。
Universal CRT (UCRT) 的出现
从 Visual Studio 2015 开始,CRT 升级成了 Universal CRT (UCRT) 。UCRT 是操作系统级别的组件,作为 Windows 的一部分,提供跨版本的 C 运行时支持。
MSVCRT(Microsoft Visual C++ 运行时)被淘汰的原因主要有:
- 向后兼容性问题,它未能跟上时代,不兼容C99标准,并且缺少一些特性。例如,它不兼容C99标准中的printf()函数族
- 它不支持UTF-8本地化设置,因此跨平台性很差
- 与MSVCRT链接的二进制文件不应该与