静态库.a在编译时被完整链接进可执行文件,运行时不依赖外部库;动态库.so在运行时才加载,需确保其路径在/usr/lib等系统目录或通过ld_library_path指定,否则报“找不到库”错误。

直接链接生成可执行文件并运行
静态库本身不能单独运行,唯一可靠测试方式是把它和主程序一起编译成可执行文件,再执行。只要能跑通,就说明 libxxx.a 里函数符号完整、ABI 兼容、没被 strip 掉。
常见错误现象:undefined reference to 'hello' —— 多半是头文件声明和实现不一致,或 ar 打包时漏了某个 .o 文件。
- 确保主程序(如
main.c)正确包含头文件,且调用的函数名与.c中定义完全一致(注意大小写、参数类型) - 用
gcc main.c libmyhello.a -o test最简方式链接,避免-L/-l引入路径干扰 - 若报错
cannot find -lc,说明系统缺少glibc-static包(Ubuntu 上装libc6-dev通常够用;CentOS/RHEL 需额外装glibc-static)
用 ar -t 和 nm 检查库内容是否完整
光靠编译不报错还不够——可能函数存在但符号被优化掉,或目标文件架构不匹配(比如 x86_64 库给 aarch64 板子用)。得手动验证 .a 里真有你需要的东西。
ar -t libmyhello.a 列出归档内所有成员,确认 hello.o 在里面;nm -C libmyhello.a | grep hello 查看符号是否为 T(全局定义)而非 U(未定义)。
-
nm -C的-C是 demangle C++ 符号,对纯 C 也安全;没加会看到 _Z6helloPKc 这类乱码 - 如果
nm输出全是U或空,说明hello.o编译时用了-fPIC(不该用于静态库)或根本没导出符号(比如函数加了static) - 交叉编译时,务必用对应 target 的
arm-linux-gnueabihf-nm而非宿主机nm
删掉 .a 文件后仍能运行,才是静态库真正生效
这是最朴素但最关键的验证:静态库必须在编译期“埋进”可执行文件,运行时不依赖外部文件。删了库还能跑,才说明不是误连了动态库或系统同名库。
- 先正常编译:
gcc main.c libmyhello.a -o app - 立刻删库:
rm libmyhello.a - 直接执行:
./app—— 成功输出即通过 - 如果失败,检查是否实际链接的是系统里同名的
/usr/lib/libmyhello.so(用ldd app看是否列出了libmyhello.so)
静态库测试容易忽略的点
很多人在虚拟机里测通了,一到开发板就崩,问题往往不在代码逻辑,而在工具链和 ABI 细节。
- 静态库必须和主程序用同一套 ABI(比如都用
arm-linux-gnueabihf-工具链),混用 host gcc 和 cross gcc 生成的.o会导致链接成功但运行段错误 -
ar版本差异极小,但某些嵌入式工具链自带的ar不支持-D(Deterministic)选项,用ar rcs替代ar rcsv更稳妥 - 开发板上
file app输出里带statically linked才算真正静态;若显示dynamically linked,说明你链接时没压住动态依赖(比如忘了加-static-libgcc)











