C 标准库
预计时间: 6分钟
简介
C标准库(C standard library 或 libc)也称为 ISO C 库,是 ISO C 标准中指定的 C 编程语言的标准库。
C 标准库为字符串处理、数学计算、输入/输出处理、内存管理和操作系统服务等任务提供宏、类型定义和函数。
在1970年代,C语言变得越来越流行。 许多大学和组织开始为自己的项目创建自己的语言变体。 到1980年代初,各种C实现之间的兼容性问题变得很明显。
1983年,美国国家标准协会(ANSI)成立了一个委员会来建立称为“ANSI C”的C标准规范。 这项工作最终在1989年创建了所谓的C89标准。 由此产生的标准的一部分是一组称为 ANSI C 标准库的软件库。
头文件
C 标准库的应用程序编程接口(API) 在许多头文件中声明。每个头文件都包含一个或多个函数声明、数据类型定义和宏。
文档
在类 Unix 系统上,实际实现的 API 的权威文档以手册页(man pages)的形式提供。 在大多数系统上,标准库函数的手册页在第3节和第7节。
GNU C 库(glibc) 为 GNU/Linux 系统以及许多其他使用 Linux 作为内核的系统提供核心库。 glibc 手册可在此处在线获取。 该手册包含规范的 API 描述。glibc 项目不维护任何手册页; 相反,其他项目将 glibc API 记录为手册页。 最大的此类集合是 Linux 手册页项目。
实现
类 Unix系统通常具有共享库形式的 C 库,但安装时可能不存在头文件(和编译器工具链),因此可能无法进行 C 开发。
- C 库是类 Unix 操作系统的一个组成部分。
- C 函数,包括 ISO C 标准函数,不仅是 C 语言中某些东西的实现,更是操作系统接口的一部分。
- 如果没有 C 库,类 Unix 操作系统通常无法运行。这适用于动态与静态链接的应用程序。
- 内核本身(至少在 Linux 的情况下)独立于任何库运行。
在 Windows 上,核心系统动态库(DLL)提供了 C 标准库的实现。
- C 库中的函数不被视为 Microsoft Windows 的接口。
编译器内置函数
一些编译器提供了 C 标准库中许多函数的内置版本,即函数的实现被写入编译后的目标文件,程序调用内置版本而不是C共享库中的函数。
问题和解决方法
缓冲区溢出漏洞
C 标准库中的一些函数因存在缓冲区溢出漏洞而臭名昭著,并且自采用以来通常鼓励错误编程。最受批评的项目是:
strcpy()
和strcat()
缺少边界检查- 一般的字符串例程,不总是保证有效的以空值结尾的输出
printf()
在格式字符串与给定参数不匹配时破坏执行堆栈。这个基本缺陷造成了一整类攻击:格式字符串攻击;gets()
和scanf()
缺少输入长度检查。
除了 gets()
,所有安全漏洞都可以通过引入辅助代码来执行内存管理、边界检查、输入检查等来避免。
这通常以包装器的形式完成,使标准库函数更安全、更易于使用。
这可以追溯到B. Kernighan 和 R. Pike 所著的《编程实践》一书中,作者通常使用包装器来打印错误消息并在发生错误时退出程序。
ISO C 委员会发布了技术报告 TR 24731-1,并正在研究 TR 24731-2,以提议采用一些具有相应边界检查和自动缓冲区分配的功能。
TR 24731-1 已在 Microsoft 的 C 标准库中实现,并且其编译器在使用旧的“不安全”函数时会发出警告。
线程问题,竞争条件的脆弱性
strerror()
线程不安全并且容易受到竞争条件的影响。
错误处理
C 标准库中函数的错误处理并不一致,有时令人困惑。
更新于2022年04月14日