🔍 什么是 CRT?—— C Runtime Library(C运行时库)
CRT 是 C Runtime Library 的缩写,中文叫“C 运行时库”,它是 C 程序在运行过程中所依赖的一组标准函数和初始化逻辑。
🎯 学习目标
理解 CRT 的定义与作用
明白为什么即使你只写了 main(),程序也能正常运行
掌握 CRT 如何初始化程序环境、调用 main() 并退出
了解 CRT 在不同平台(Windows / Linux)下的差异
✅ 一、CRT 是什么?
定义:
CRT 是 C 程序运行前必须完成的准备工作 + 提供的标准函数集合。
它不是你写的代码的一部分,而是由编译器自动链接到你的程序中的一段支持代码。
✅ 二、CRT 的核心功能
1. 初始化程序环境
设置堆栈(Stack)
初始化堆(Heap)
解析命令行参数(argc, argv)
初始化标准输入输出(stdin/stdout/stderr)
调用全局构造函数(C++)
2. 调用你的 main() 函数
在准备好一切之后,CRT 才会跳转到你写的 main() 函数。
3. 处理程序退出
捕获异常或错误
调用 exit() 清理资源
返回操作系统
✅ 三、从 CRT 到 main():一个完整的流程图
操作系统加载 exe → 入口点 _start(CRT 启动代码)
↓
初始化堆栈、堆、IO等
↓
解析命令行参数 argc/argv
↓
调用 __tmainCRTStartup(CRT 主启动函数)
↓
调用 main()
↓
main() 返回,执行 exit()
↓
CRT 清理并返回操作系统
📌 你的 main() 只是这个流程中的一小部分。
✅ 四、CRT 在 Windows 下的典型实现(以 MinGW-w64 为例)
CRT 包括以下几个关键函数(都在 .text 段中):
函数名
功能
_start 或 mainCRTStartup
程序入口点
__tmainCRTStartup
CRT 主启动函数,调用 main
pre_c_init / pre_cpp_init
初始化 C/C++ 支持
exit()
退出处理
malloc() / free()
内存管理
printf() / scanf()
标准 IO 函数
你可以通过反汇编看到这些函数的机器码。
✅ 五、CRT 在 Linux 下的典型实现(glibc)
Linux 上的 CRT 更加标准化:
启动函数为 _start
位于 /usr/lib/x86_64-linux-gnu/crt1.o
最终调用 __libc_start_main(),再调用 main()
gcc -v hello.c
你会看到类似这样的链接过程:
/usr/bin/ld ... crt1.o crti.o crtbegin.o ... your_code.o ... crtend.o crtn.o
📌 这些 .o 文件就是 CRT 的组成部分。
✅ 六、动手实验:禁用 CRT,看看会发生什么
你可以尝试不使用 CRT 来编译程序,观察程序行为:
示例代码:hello.S
.global _start
_start:
mov $1, %rax # sys_write
mov $1, %rdi # fd=stdout
lea msg(%rip), %rsi # buffer address
mov $13, %rdx # length
syscall
xor %rdi, %rdi # exit code 0
mov $60, %rax # sys_exit
syscall
msg:
.asciz "Hello World\n"
编译命令:
as hello.S -o hello.o
ld hello.o -o hello
./hello
📌 这个程序没有 main(),也没有任何 CRT 初始化逻辑,但它依然可以运行!
✅ 七、CRT 和标准库的区别
名称
全称
内容
特点
CRT
C Runtime
初始化逻辑 + 标准库一部分
编译器自动链接
C Standard Library
C 标准库
需要手动包含头文件
STL(C++)
Standard Template Library
vector、map、algorithm 等
C++ 特有
📌 CRT 是标准库的一部分,但更底层。
✅ 八、CRT 的静态链接 vs 动态链接
类型
描述
使用方式
静态链接 CRT
CRT 代码直接打包进可执行文件
-static 编译选项
动态链接 CRT
CRT 作为 DLL 加载(如 msvcrt.dll)
默认方式
📌 静态链接体积大,但独立性强;动态链接体积小,但依赖系统 DLL。
✅ 九、总结:CRT 的本质是什么?
CRT = 程序运行前的准备 + main() 的调用者 + 程序结束的清理者
你可以把它想象成:
“一个看不见的助手,在你写 main() 之前就已经开始工作了。”
✅ 十、延伸思考:如果你不用 CRT,你能做什么?
写最小可执行文件(如上例)
实现自己的运行时逻辑
开发操作系统内核
研究逆向工程、病毒分析、安全加固等领域
📌 下一步建议:
如果你想继续深入:
👉《如何从零构建一个 CRT》
👉《ELF/PE 文件格式详解》
👉《函数调用栈与堆栈平衡》
👉《JVM / Python 虚拟机的 CRT 对应机制》
或者我也可以为你生成一份《CRT 源码解析指南》,帮助你阅读 GCC 或 MSVC 的 CRT 实现源码。
是否需要?欢迎告诉我你的兴趣方向!🚀