为何链接static库与shared库生成的executable文件大小一致?
静态库与动态库链接后可执行文件大小相同的问题
我学习静态库(static)与动态库(shared)的区别时了解到:链接静态库生成的可执行文件体积更大,因为静态库会直接成为可执行文件的一部分;而链接动态库时,动态库并不会并入可执行文件,而是在运行时完成链接。但实际测试中,我分别链接两种库生成的可执行文件大小完全相同,以下是我的测试代码:
测试代码
root/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1) project(hello_world) add_executable(my_app main.cpp) add_subdirectory( ${CMAKE_CURRENT_SOURCE_DIR}/lib ) target_link_libraries(my_app PRIVATE my_lib) target_include_directories(my_app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../include)
main.cpp
#include<iostream> #include "mymath.h" int main() { std::cout<<sum(2,4)<<std::endl; std::cout<<mul(2,4); }
lib/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1) add_library(my_lib SHARED math.cpp) // 改成STATIC后,my_app的大小也没变化 target_include_directories(my_lib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../include)
lib/math.cpp
#include<iostream> #include "mymath.h" int sum(int a, int b) { return a+b; } int mul(int a, int b) { return a*b; }
原因分析
- 编译器内联优化:
sum和mul是极简单的函数,编译器默认开启的优化(如-O2)会直接将这些函数的代码内联到main函数中,完全没有实际链接库文件里的代码。不管是静态库还是动态库,可执行文件都直接包含内联后的计算逻辑,因此大小一致。 - 静态库链接特性:静态库是目标文件集合,链接器只会打包可执行文件用到的部分,但函数被内联后,链接器甚至不会读取静态库中的对应目标文件。
- 动态库符号处理:链接动态库时,若函数被内联,可执行文件不会依赖动态库中的符号,而是直接包含内联代码,所以大小和静态库链接的情况无差异。
验证方法
- 关闭编译器优化:在CMakeLists.txt中添加
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0"),强制关闭优化,让编译器无法内联简单函数。 - 增加库函数复杂度:在
sum或mul中添加循环、内存操作等复杂逻辑,使编译器无法内联,此时再对比两种库生成的可执行文件大小,就能看到明显差异。
内容的提问来源于stack exchange,提问作者Vivek Mangal
相关产品推荐
相关产品推荐

