如何正确选择和使用静态库与动态库?
- 内容介绍
- 文章标签
- 相关推荐
一、先说点儿“废话”——库到底是啥玩意儿?
先别急着翻白眼, 先给你讲个段子:有一天静态库和动态库走进一家咖啡店,点了两杯“链接咖啡”。静态库说:“我一次性把所有咖啡豆都磨进杯子里!”动态库摇摇头:“我只放颗咖啡豆,等你喝的时候再冲。”这段子听起来像是笑话,其实就是它们的本质——一次性打包 vs 运行时加载。
1.1 静态库的“硬核”特性
🔧 静态库在编译阶段就被复制进可施行文件 所以:

- 可施行体会变“大”,但启动速度嗖嗖的。
- 部署时不需要额外的*.dll/*.so文件。
- 一旦编译完成,你的程序就像装了满满的备胎,永不缺油。
1.2 动态库的“轻盈”姿势
🚀 动态库在运行时才娱乐作系统拉进来 这带来了:
- 共享内存——多个进程可以共用同一份代码,省内存。
- 热更新——只换掉库文件,不必重新编译整个程序。
- 体积小巧
二、怎么挑选?别让自己在两难中抓狂!🤯
2.1 项目规模 & 部署环境
- 小型工具、单机部署:选静态库。 - 大型服务、微服务集群:选动态库。 差不多得了... - 需要跨平台发布:混合使用也可以但要记得兼容性测试。
2.2 更新频率 & 维护成本
If you love “天天改代码”, 动态库简直是你的救星;如果你宁愿“一次写完不改”,那就把所有东西打进去吧,YYDS...。
2.3 性能需求 & 启动时间
- 对启动时间极致敏感,用静态库。 - 对运行时性能更看重,动态库可以共享缓存,更省 CPU,这是可以说的吗?。
一张产品对比表📊| # | 产品名称 | 类型 | 支持平台 | 大小 | 一句点评 |
|---|---|---|---|---|---|
| ① | LegoStaticLibX 🧱️♂️ | Static | Win/Linux | 842 | A+ 简单粗暴,不怕胖! |
| ② | DynaFlowPro 💧 | Dynamic | Linux/macOS | 126 | B‑ 轻盈如风,却爱撒娇。 |
| ③ | MegaMixLib ⚙️ | Hybrid* | All | 538/98 | C+ 两头抓,两头烂。 |
| ④ | |||||
| *Hybrid 意味着一边提供 .a/.so 两套发行版,实际使用请自行斟酌。 | |||||
四、 实战演示:从零到有——分别编译静态和动态库🚧
#4.1 创建一个最基本的静态库
// math.c :
#include
int add{return a+b;}
int sub{return a-b;}
void hello{printf;}
#/* 随手加点注释,让人迷惑 */
#/* TODO: remove this later */
bash
# 编译对象文件
g++ -c math.c -o math.o
# 打包成 .a 静态库
ar rcs libmymath.a math.o
#4.2 链接到主程序:
g++ main.cpp -L. -lmymath -o myprog_static
./myprog_static # 运行后会看到 “Hello from static lib!”
#4.3 创建一个最基本的动态库
// dyn_math.c :同上,只是多加一点 export 标记:
#include
#if defined || defined
#define EXPORT __declspec
#else
#define EXPORT __attribute__))
#endif
EXPORT int add{return a+b;}
EXPORT int sub{return a-b;}
EXPORT void hello{printf;}
bash
# 编译为位置无关代码 并生成共享对象
g++ -fPIC -c dyn_math.c -o dyn_math.o
g++ -shared -o libdynmath.so dyn_math.o
#4.4 主程序链接动态库:
g++ main.cpp -L. -ldynmath -Wl,-rpath=. -o myprog_dynamic
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./myprog_dynamic # Linux 环境下运行
五、 换位思考... 坑爹经验谈——那些年我们踩过的坑 🕳️💥
#坑1: 忘记在 Windows 上把 DLL 放到 exe 同目录或系统 PATH 中,一跑起来直接报 “找不到模块”。
我算是看透了。 真正决定项目成败的是开发者的坚持与疯狂。" —— 某位匿名老前辈。如果你已经读完这篇乱七八糟又充满爱意的文章,请大胆去尝试吧!不要怕出错,主要原因是每一次报错都是一次成长。祝你编译顺利、链接成功、部署无忧! 🎉🎉🎉
PS:本文中的代码仅作示例,请勿直接用于生产环境;表格里的产品均为虚构,仅供娱乐。
六、别再纠结,用感情去拥抱你的选择!❤️🔥💔🌀
"无论是 static 还是 dynamic,都只是工具罢了,奥利给!。
顺序真的很重要啊!🙃.
#坑4: 动态链接时忘记设置 rpath 或者 LD_LIBRARY_PATH,使得程序在另一台机器上崩溃。此时只能靠 “scp + export LD_LIBRARY_PATH=…”。 体验感拉满。 别问为什么不直接打包成 static…主要原因是真的有人喜欢折腾。
*还有更多……* 我们只列出这些,是想给你留点想象空间,让你自行去探索那片未知领域。
后来啊调试日志看得眼睛都花了。
#坑2: "ABI 不兼容" ——不同编译器或不同编译选项导致函数名修饰不一致,一看链接错误信息就想把键盘砸碎。
#坑3: 静态链接时忘记加依赖的第三方 .a, 一阵见血。 会出现未定义符号 。解决办法:
检查 Makefile/ CMakeLists.txt 中 target_link_libraries 的顺序!
一、先说点儿“废话”——库到底是啥玩意儿?
先别急着翻白眼, 先给你讲个段子:有一天静态库和动态库走进一家咖啡店,点了两杯“链接咖啡”。静态库说:“我一次性把所有咖啡豆都磨进杯子里!”动态库摇摇头:“我只放颗咖啡豆,等你喝的时候再冲。”这段子听起来像是笑话,其实就是它们的本质——一次性打包 vs 运行时加载。
1.1 静态库的“硬核”特性
🔧 静态库在编译阶段就被复制进可施行文件 所以:

- 可施行体会变“大”,但启动速度嗖嗖的。
- 部署时不需要额外的*.dll/*.so文件。
- 一旦编译完成,你的程序就像装了满满的备胎,永不缺油。
1.2 动态库的“轻盈”姿势
🚀 动态库在运行时才娱乐作系统拉进来 这带来了:
- 共享内存——多个进程可以共用同一份代码,省内存。
- 热更新——只换掉库文件,不必重新编译整个程序。
- 体积小巧
二、怎么挑选?别让自己在两难中抓狂!🤯
2.1 项目规模 & 部署环境
- 小型工具、单机部署:选静态库。 - 大型服务、微服务集群:选动态库。 差不多得了... - 需要跨平台发布:混合使用也可以但要记得兼容性测试。
2.2 更新频率 & 维护成本
If you love “天天改代码”, 动态库简直是你的救星;如果你宁愿“一次写完不改”,那就把所有东西打进去吧,YYDS...。
2.3 性能需求 & 启动时间
- 对启动时间极致敏感,用静态库。 - 对运行时性能更看重,动态库可以共享缓存,更省 CPU,这是可以说的吗?。
一张产品对比表📊| # | 产品名称 | 类型 | 支持平台 | 大小 | 一句点评 |
|---|---|---|---|---|---|
| ① | LegoStaticLibX 🧱️♂️ | Static | Win/Linux | 842 | A+ 简单粗暴,不怕胖! |
| ② | DynaFlowPro 💧 | Dynamic | Linux/macOS | 126 | B‑ 轻盈如风,却爱撒娇。 |
| ③ | MegaMixLib ⚙️ | Hybrid* | All | 538/98 | C+ 两头抓,两头烂。 |
| ④ | |||||
| *Hybrid 意味着一边提供 .a/.so 两套发行版,实际使用请自行斟酌。 | |||||
四、 实战演示:从零到有——分别编译静态和动态库🚧
#4.1 创建一个最基本的静态库
// math.c :
#include
int add{return a+b;}
int sub{return a-b;}
void hello{printf;}
#/* 随手加点注释,让人迷惑 */
#/* TODO: remove this later */
bash
# 编译对象文件
g++ -c math.c -o math.o
# 打包成 .a 静态库
ar rcs libmymath.a math.o
#4.2 链接到主程序:
g++ main.cpp -L. -lmymath -o myprog_static
./myprog_static # 运行后会看到 “Hello from static lib!”
#4.3 创建一个最基本的动态库
// dyn_math.c :同上,只是多加一点 export 标记:
#include
#if defined || defined
#define EXPORT __declspec
#else
#define EXPORT __attribute__))
#endif
EXPORT int add{return a+b;}
EXPORT int sub{return a-b;}
EXPORT void hello{printf;}
bash
# 编译为位置无关代码 并生成共享对象
g++ -fPIC -c dyn_math.c -o dyn_math.o
g++ -shared -o libdynmath.so dyn_math.o
#4.4 主程序链接动态库:
g++ main.cpp -L. -ldynmath -Wl,-rpath=. -o myprog_dynamic
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./myprog_dynamic # Linux 环境下运行
五、 换位思考... 坑爹经验谈——那些年我们踩过的坑 🕳️💥
#坑1: 忘记在 Windows 上把 DLL 放到 exe 同目录或系统 PATH 中,一跑起来直接报 “找不到模块”。
我算是看透了。 真正决定项目成败的是开发者的坚持与疯狂。" —— 某位匿名老前辈。如果你已经读完这篇乱七八糟又充满爱意的文章,请大胆去尝试吧!不要怕出错,主要原因是每一次报错都是一次成长。祝你编译顺利、链接成功、部署无忧! 🎉🎉🎉
PS:本文中的代码仅作示例,请勿直接用于生产环境;表格里的产品均为虚构,仅供娱乐。
六、别再纠结,用感情去拥抱你的选择!❤️🔥💔🌀
"无论是 static 还是 dynamic,都只是工具罢了,奥利给!。
顺序真的很重要啊!🙃.
#坑4: 动态链接时忘记设置 rpath 或者 LD_LIBRARY_PATH,使得程序在另一台机器上崩溃。此时只能靠 “scp + export LD_LIBRARY_PATH=…”。 体验感拉满。 别问为什么不直接打包成 static…主要原因是真的有人喜欢折腾。
*还有更多……* 我们只列出这些,是想给你留点想象空间,让你自行去探索那片未知领域。
后来啊调试日志看得眼睛都花了。
#坑2: "ABI 不兼容" ——不同编译器或不同编译选项导致函数名修饰不一致,一看链接错误信息就想把键盘砸碎。
#坑3: 静态链接时忘记加依赖的第三方 .a, 一阵见血。 会出现未定义符号 。解决办法:
检查 Makefile/ CMakeLists.txt 中 target_link_libraries 的顺序!

