【问题标题】:What is the C runtime library?什么是 C 运行时库?
【发布时间】:2011-02-15 12:16:36
【问题描述】:

什么是 C 运行时库,它的用途是什么?我在搜索,像魔鬼一样用谷歌搜索,但我找不到比 Microsoft 更好的东西了:“Microsoft 运行时库为 Microsoft Windows 操作系统的编程提供了例程。这些例程自动化了许多常见的编程任务,而这些任务不是由C 和 C++ 语言。”

好的,我明白了,但是例如,libcmt.lib 中的内容是什么?它有什么作用?我认为 C 标准库是 C 编译器的一部分。那么libcmt.libwindows实现的C标准库函数是否可以在win32下工作?

【问题讨论】:

标签: c runtime


【解决方案1】:

是的,libcmt 是微软编译器提供的 C 标准库的(几个)实现。它们提供三种基本类型库的“调试”和“发布”版本:单线程(始终静态链接)、多线程静态链接多线程动态链接(不过,根据您使用的编译器版本,其中一些可能不存在)。

因此,在名称“libcmt”中,“libc”是(或多或少)C 库的传统名称。 “mt”的意思是“多线程”。 “调试”版本的末尾会添加一个“d”,给出“libcmtd”。

就其包含的功能而言,C 标准(第 7 部分,如果您碰巧关心的话)定义了一组符合(托管)实现必须提供的功能。大多数供应商(包括 Microsoft)自己添加了各种其他功能(为了兼容性,提供标准功能未解决的功能等)。在大多数情况下,它还将包含相当多的编译器使用的“内部”功能但最终用户通常不会。

运行时库基本上是一个大文件(或几个大文件——例如,在 UNIX 上,浮点函数传统上与其余函数分开存储)中这些函数的实现的集合。该大文件通常与 zip 文件具有相同的一般顺序,但没有任何压缩,因此它基本上只是一些小文件收集在一起并一起存储到一个更大的文件中。存档通常至少包含一些索引,以使其相对快速/容易地从内部文件中查找和提取数据。至少有时,微软使用了一种带有“扩展”索引的库格式,链接器可以使用它来查找在哪些子文件中实现了哪些函数,因此它可以更快地找到并链接它需要的部分(但那是纯粹是优化,不是要求)。

如果您想获得“libcmt”中函数的完整列表(使用您的示例),您可以打开 Visual Studio 命令提示符之一(通常在“Visual Studio 工具”下),切换到其中的目录您的库已安装,并键入类似:lib -list libcmt.lib 它将生成一个 (long) 该库中所有目标文件名称的列表。这些并不总是直接对应于函数的名称,但通常会给出一个想法。如果您想查看特定的目标文件,可以使用lib -extract 提取其中一个目标文件,然后使用dumpbin /symbols <object file name> 查找该特定目标文件中的函数。

【讨论】:

  • 你还没告诉“C运行时库”是什么!!
  • @entropy:在我看来确实和我一样,但简短的回答是它是函数的集合,其中许多(但不一定全部)在 C 标准的第 7 部分中指定。
  • 这个答案意味着 C 库只是编译器工具链的一部分。不准确。
  • @JerryCoffin 问题:例如,来自 C 标准库的 strcpy 函数是否会在运行时库中实现,或者只是在普通的 .c 文件中实现代码?
  • 所以C运行时库基本上是微软对标准C库的引用方式?
【解决方案2】:

首先,我们应该了解什么是运行时库;并思考“Microsoft C 运行时库”的含义。

见:http://en.wikipedia.org/wiki/Runtime_library

我已经在这里发布了大部分文章,因为它可能会更新。

当一个计算机程序的源代码被编译器翻译成相应的目标语言时,如果程序中的每一条命令和对内置函数的每一次调用都会导致-每次在目标语言中生成完整的相应程序代码。相反,编译器通常在运行时库中使用编译器特定的辅助函数,这些函数对于应用程序程序员来说大多是不可访问的。根据编译器制造商的不同,运行时库有时也会包含相应编译器的标准库或包含在其中。

还有一些只能在运​​行时执行(或者更有效或更准确)的功能在运行时库中实现,例如一些逻辑错误、数组边界检查、动态类型检查、异常处理和可能的调试功能。出于这个原因,尽管有复杂的编译时检查和预发布测试,但直到在具有真实数据的“实时”环境中对程序进行测试后,才会发现一些编程错误。在这种情况下,最终用户可能会遇到运行时错误消息。

通常运行时库通过访问操作系统来实现很多功能。许多编程语言都有内置函数,不一定要在编译器中实现,但可以在运行时库中实现。因此运行时库和标准库之间的界限取决于编译器制造商。 因此,运行时库始终是特定于编译器和特定平台的。

运行时库的概念不应与由应用程序员创建或由第三方交付的普通程序库或动态库(即在运行时链接的程序库)混淆。例如,编程语言 C 只需要一个最小的运行时库(通常称为 crt0),但定义了一个大型标准库(称为 C 标准库),每个实现都必须交付。

【讨论】:

  • 突出显示的句子作为区别于标准库的一种方式是我见过的第一个简洁准确的答案,不符合“大多数”或“有时”。
  • @nik.shornikov:那是因为其他描述试图更准确。尽管标准库确实通常特定于编译器和平台,但这并不总是正确的。例如,至少有一些版本的 Mingw 和英特尔的 C++ 编译器都使用了微软的标准库,而不是提供自己的标准库。同样,可以(并且经常)安装 Linux 上的 Clang 以在现有的 gcc 安装中使用标准库,而不是为自己安装另一个。
  • 我有理由确定可以编写可移植到任何支持 POSIX 的平台的 C 和 C++ 标准库的实现。
【解决方案3】:

我只是自己问过这个问题,这让我的大脑受伤了几个小时。仍然没有找到任何真正有意义的东西。每个确实为某个主题写东西的人都无法真正“教”。如果你想教一个人,就拿一个人懂的最基本的语言,这样他在处理一个话题时就不需要关心其他话题。所以我为自己得出了一个似乎很适合所有这些混乱的结论。

在编程语言 C 中,每个程序都以 main() 函数开头。 其他语言可能会定义程序启动的其他功能。但是处理器不知道main()。处理器只知道预定义的命令,由01 的组合表示。

在没有底层操作系统(Microsoft Windows、Linux、MacOS 等)的微处理器编程中,您需要通过设置迭代和跳转(循环,函数调用)在处理器已知的命令中。你需要知道RAM有多大,需要设置程序栈的位置(局部变量),还有堆的位置(动态变量)和全局变量的位置(我猜是叫SSA ?) 在 RAM 中。 单个处理器一次只能执行一个程序。

这就是操作系统的用武之地。操作系统本身就是在处理器上运行的程序。允许执行自定义代码的程序。通过在程序的执行代码(加载到 RAM 中)之间切换来一次运行多个程序。但是操作系统是一个程序,每个程序的编写方式都不同。简单地将自定义程序的代码放入 RAM 不会运行它,操作系统不知道它。您需要调用操作系统上注册程序的函数,告诉操作系统程序需要多少内存,程序的入口点在哪里(C 语言中的main() 函数)。我猜这就是运行时库中的内容,并解释了为什么每个操作系统都需要一个特殊的库,因为这些只是程序本身,并且具有不同的功能来执行这些操作。

这也解释了为什么它不像.dll 文件那样在运行时动态链接,即使它被称为运行时库。运行时库需要静态链接,因为在程序启动时需要它。运行时库在运行时将您的自定义程序注入/连接到另一个程序(操作系统)。这真的会引起一些大脑f...

结论: RUNTIME 库命名失败。早期可能没有.dll(在运行时链接),理解差异的问题根本不存在。但即使这是真的,这个名字也选得不好。

运行时库的更好名称可能是:StartupLibrary/OSEntryLibrary/SystemConnectLibrary/OSConnectLibrary

希望我做对了,以便进行更正/扩展。 干杯。

【讨论】:

  • 我还是不明白。为什么程序在运行时需要一些东西?为什么二进制代码不能运行,100% 单独运行,运行时没有任何支持?或者换句话说:是否有可能在没有任何东西(包括操作系统)的情况下运行 100% 的代码?
  • 理论上程序不需要 RTL。但是,如果没有操作系统的合作,您的程序将如何显示其结果或获取任何输入或请求内存?
  • 这是这个问题最容易理解的答案,谢谢。问题仍然是“启动库”是否也实现了 C 标准库?就像 C 标准定义库的规范一样,就像 C++ 的情况一样,这个库是否也实现了相同的功能?请我需要关于这个话题的启示。
  • 您认为需要 C 运行时才能通过提供 main() 的地址来启动程序并且 C 运行时库不是动态链接的结论是错误的。可执行文件(例如 ELF 可执行文件)包含入口点地址,以及在操作系统上运行程序所需的其他信息。另外,Microsoft C Runtime 的名称应该可以为您提供线索,它被称为“msvcrt.dll”。
【解决方案4】:

C 是一种语言,在其定义中,您不需要任何可用的函数。没有 IO,没有数学例程等等。按照惯例,有一组例程可供您使用,您可以将它们链接到您的可执行文件中,但您不需要 使用它们。然而,这是一种常见的做法,大多数链接器不再要求您链接到 C 运行时库。

有时您不想要它们 - 例如,在使用嵌入式系统时,使用 malloc 可能是不切实际的。我曾经致力于将 PostScript 嵌入到打印机中,我们有自己的一组运行时库,这些库在嵌入式系统上更受欢迎,所以我们没有为“标准”而烦恼。

【讨论】:

  • 实际上,C 标准描述了两种类型的 C 环境——“独立”和“托管”——并且,在托管环境中,标准中描述的功能定义可用。在嵌入式系统中,C 环境通常是独立的,因此您可能没有库例程,或者您可以避免使用一些并使用您自己的替代品。
【解决方案5】:

运行时库是为您运行的任何 C 程序自动编译的库。您将使用的库版本取决于您的编译器、平台、调试选项和多线程选项。

很好地描述了运行时库的不同选择: http://www.davidlenihan.com/2008/01/choosing_the_correct_cc_runtim.html

它包括那些你通常认为不需要库来调用的函数:

  • malloc
  • 枚举,结构
  • 腹肌,分钟
  • 断言

Microsoft 有一个很好的运行时库函数列表:

http://msdn.microsoft.com/en-us/library/2aza74he(VS.71).aspx

函数的确切列表会因编译器而异,因此对于 iOS,您将获得其他函数,例如 dispatch_async() 或 NSLog()。

【讨论】:

  • struct 和 enum 真的是运行时库吗?
【解决方案6】:

如果您在从 C 或 C++ 编译的可执行文件上使用像 Dependency Walker 这样的工具,您会看到它所依赖的 DLL 之一是 MSVCRT.DLL。这是 Microsoft C 运行时库。如果您进一步使用 DW 检查 MSVCRT.DLL,您会发现这是所有函数(如 printf()、puts(0、gets()、atoi() 等)所在的位置。

【讨论】:

  • 仅当编译该可执行文件时,C 运行时是动态链接的。如果它是静态链接的,则依赖遍历器将不显示任何内容
【解决方案7】:

我认为微软的定义真的意味着:

微软的实现 标准 C 运行时库提供...

【讨论】:

    【解决方案8】:

    Win32 SDK 提供了三种形式的 C 运行时库:

    * LIBC.LIB is a statically linked library for single-threaded programs.
    * LIBCMT.LIB is a statically linked library that supports multithreaded programs.
    * CRTDLL.LIB is an import library for CRTDLL.DLL that also supports multithreaded programs. CRTDLL.DLL itself is part of Windows NT. 
    

    Microsoft Visual C++ 32 位版本也包含这三种形式,但是,DLL 中的 CRT 名为 MSVCRT.LIB。 DLL 是可再分发的。它的名称取决于 VC++ 的版本(即 MSVCRT10.DLL 或 MSVCRT20.DLL)。但是请注意,Win32 不支持 MSVCRT10.DLL,而 Win32 支持 CRTDLL.LIB。 MSVCRT20.DLL 有两个版本:一个用于 Windows NT,另一个用于 Win32s。

    见:http://support.microsoft.com/?scid=kb%3Ben-us%3B94248&x=12&y=9

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-13
      • 2019-03-08
      • 2011-05-11
      • 2017-07-27
      • 1970-01-01
      • 2011-04-23
      • 1970-01-01
      相关资源
      最近更新 更多