我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

程序运行的一生

程序运行的一生 构建四步曲与静态/动态链接B 站视频笔记目录构建四步曲与静态/动态链接B 站视频笔记学习目标学习内容一、全景图程序的一生 构建阶段 运行阶段二、构建阶段四步曲1. 预处理-E文本替换处理器2. 编译-S真正的翻译官3. 汇编-c机械翻译4. 链接符号解析 地址重定位三、静态库 vs 动态库区别只在何时解析代码四、运行时加载的三个要点五、手动构建撑不起真实项目 → CMake六、结尾学习目标1.说清 C/C 源代码变成运行中程序的完整六步预处理 → 编译 → 汇编 → 链接 → 加载 → CPU 执行2. 分清静态库与动态库的本质区别——“何时解析代码”并能动手验证3. 记住构建四步曲各阶段的产物与典型报错会排查 undefined reference4. 理解 PIC 位置无关代码、运行时找库失败的原因以及 CMake 到底是什么学习内容一、全景图程序的一生 构建阶段 运行阶段源代码 .c / .cpp │ ① 预处理(-E) → main.i 展开 #include / #define、删注释、条件编译 │ ② 编译(-S) → main.s 词法/语法/语义分析 优化生成汇编 │ ③ 汇编(-c) → main.o 汇编 → 机器码机械翻译不会出错 │ ④ 链接 → ELF / EXE 符号解析 地址重定位 ▼ 运行阶段⑤ 加载器加载动态库等依赖 → ⑥ CPU 执行二、构建阶段四步曲1. 预处理-E文本替换处理器展开#include和#define、删除注释、处理条件编译本质是文本替换不理解任何语义典型报错No such file or directory头文件找不到命令gcc -E main.c -o main.i。2. 编译-S真正的翻译官词法 / 语法 / 语义分析 优化把 C/C 翻译成汇编代码典型报错语法错误最常出错的阶段命令gcc -S main.i -o main.s。3. 汇编-c机械翻译把汇编翻译成机器码产出目标文件 .o这一步基本不会出错——它只是上一步的机械翻译冷知识明明是Assembly 阶段选项却叫-c广义 compile历史遗留命令gcc -c main.s -o main.o。4. 链接符号解析 地址重定位合并所有 .o 和库生成可执行文件LinuxELF/ WindowsEXE典型报错undefined reference to xxx——符号没找到经典陷阱——库链接顺序链接器单向扫描被依赖的库要放在后面A 依赖 B → 写成-lA -lBA 在前、B 在后写反了就报 undefined reference。四步总表阶段选项产物会不会出错典型报错预处理-E.i会No such file or directory编译-S.s会最容易出错语法错误汇编-c.o基本不会—链接默认/-oELF / EXE会undefined reference三、静态库 vs 动态库区别只在何时解析代码静态链接动态链接链接时库代码复制嵌入可执行文件只记录引用标记“便条”运行时不依赖任何外部文件加载器按便条找库、加载、解析符号关键命令ar rcs libxxx.a *.o-fPIC -shared生成 .so / .dylib / .dll类比内嵌全文的文档自包含但更新难带超链接的文档小而新但怕链接失效适用Docker 镜像、命令行工具分发共享内存省资源、插件机制、独立升级库视频里的删除法证明两个漂亮的实验静态删掉 .a 和 .o 后静态链接的程序照常运行→ 代码已经内嵌进可执行文件动态删掉 .dylib 后动态链接的程序立即报错→ 运行时才去找库。查看依赖otool -LmacOS/lddLinux/dumpbin /dependentsWindows。实操命令清单# —— 静态库 ——gcc-cadd.c# 生成 add.oar rcs libadd.a add.o# 打包成静态库本质是 .o 的归档gcc main.c -L.-ladd-ostatic_app# 静态链接# —— 动态库 ——gcc-fPIC-sharedadd.c-olibadd.so# 位置无关 共享gcc main.c -L.-ladd-odyn_appLD_LIBRARY_PATH. ./dyn_app# 运行时告诉加载器去哪找库# —— 查看依赖 ——ldd dyn_app# Linuxotool-Ldyn_app# macOS四、运行时加载的三个要点动态库必须编译成位置无关代码PIC-fPIC让库代码可以被加载到内存任意地址多进程才能共享同一份副本两个阶段是配合关系运行时能动态加载前提是构建时链接器已在可执行文件里写好引用标记——不是运行阶段凭空完成的常见运行时错误error while loading shared libraries: libxxx.so: cannot open shared object file——加载器在标准搜索路径找不到动态库。解法① 把库放进标准路径/usr/lib② 设LD_LIBRARY_PATH③ 编译时用-Wl,-rpath把搜索路径写进可执行文件④ldconfig刷新库缓存。五、手动构建撑不起真实项目 → CMakeCMake不是构建工具是构建生成器一份CMakeLists.txtLinux 生成 Makefile、Windows 生成 .sln、macOS 生成 Xcode 工程把易错且平台不兼容的底层命令链接顺序、-fPIC、-L……全部接管。最小示例cmake_minimum_required(VERSION 3.10) project(demo) add_library(add SHARED add.c) # SHARED动态库不写默认静态 add_executable(main main.c) target_link_libraries(main PRIVATE add) # 链接顺序不用再手管六、结尾这些知识点不是为了背-fPIC、-L这类咒语——AI 时代记命令没有价值。真正要带走的是工程选型背后的永恒权衡共享与隔离、灵活与稳定。在矛盾中找到平衡点才是软件工程的哲学。
返回列表