当前位置: 首页 > news >正文

g++链接及动态库和静态库浅析

文章目录

  • 制作动态库
  • 第一个问题
  • 第二个问题
  • 为什么没用-I(大写的i)也可以?

制作动态库

  1. myprint.h文件
    #pragma once 
    void myprint();
    

    myprint.cc 文件
    #include <stdio.h>
    #include "myprint.h"
    void myprint() {
        printf("myprint\n");
    }
    
  2. 使用命令制作动态库
    [test_so_a] :) mkdir so
    [test_so_a] :) g++ -fPIC -o myprint.o -c myprint.cc 
    [test_so_a] :) g++ -shared -o libmyprint.so myprint.o 
    [test_so_a] :) mv libmyprint.so so/
    [test_so_a] :) ls -al ./so/
    total 24
    drwxrwxr-x 2 pengchen pengchen  4096 Mar 13 19:06 .
    drwxrwxr-x 3 pengchen pengchen  4096 Mar 13 19:06 ..
    -rwxrwxr-x 1 pengchen pengchen 16208 Mar 13 19:06 libmyprint.so
    [test_so_a] :) 
    
  3. 使用动态库main.cc
    
    #include "myprint.h"
    
    int main() {
        myprint();
    }
    
    生成可执行文件指令
    [test_so_a] :) g++ -E main.cc -o main_dynamic.i
    [test_so_a] :) g++ -S main_dynamic.i -o main_dynamic.s
    [test_so_a] :) g++ -c main_dynamic.s -o main_dynamic.o
    [test_so_a] :) g++ -o main_dynamic main_dynamic.o -L ./so/ -lmyprint
    [test_so_a] :) echo $LD_LIBRARY_PATH
    
    [test_so_a] :) ./main_dynamic 
    ./main_dynamic: error while loading shared libraries: libmyprint.so: cannot open shared object file: No such file or directory
    [test_so_a] :( export LD_LIBRARY_PATH=./so/:${LD_LIBRARY_PATH}
    [test_so_a] :) ./main_dynamic 
    myprint
    [test_so_a] :) 
    
    这里几个问题?
    1. 为什么在链接阶段需要添加-L(大些L)和-l(小写L,与大写的i意思完全不同)选项?
    2. 环境变量LD_LIBRARY_PATH的作用?
    3. 为什么没用-I(大写的i)也可以?

第一个问题

  1. 为什么需要-L以“编译和链接阶段,指定链接器应该搜索哪些目录以找到库文件。”?反正动态库又不放到可执行文件里面?LD_LIBRARY_PATH不就行了?

    -L 选项在编译和链接阶段起到了关键作用,确保了链接器能正确解析符号、生成符号表和依赖信息。虽然动态库本身不嵌入到可执行文件中,但这些步骤对于生成一个能够正确运行的可执行文件是不可或缺的。而 LD_LIBRARY_PATH 则是在运行时阶段工作的,保证程序在执行时能找到这些库。两者的作用和使用阶段不同,不能互相替代。

    • 验证是否具有”正确解析符号“ 功能
      [test_so_a] :) nm -AC main_dynamic.o
      main_dynamic.o:                 U _GLOBAL_OFFSET_TABLE_
      main_dynamic.o:0000000000000000 T main
      main_dynamic.o:                 U myprint()
      [test_so_a] :) nm -AC main_dynamic
      main_dynamic:0000000000004010 B __bss_start
      main_dynamic:0000000000004010 b completed.8061
      main_dynamic:                 w __cxa_finalize@@GLIBC_2.2.5
      main_dynamic:0000000000004000 D __data_start
      main_dynamic:0000000000004000 W data_start
      main_dynamic:0000000000001090 t deregister_tm_clones
      main_dynamic:0000000000001100 t __do_global_dtors_aux
      main_dynamic:0000000000003db0 d __do_global_dtors_aux_fini_array_entry
      main_dynamic:0000000000004008 D __dso_handle
      main_dynamic:0000000000003db8 d _DYNAMIC
      main_dynamic:0000000000004010 D _edata
      main_dynamic:0000000000004018 B _end
      main_dynamic:00000000000011d8 T _fini
      main_dynamic:0000000000001140 t frame_dummy
      main_dynamic:0000000000003da8 d __frame_dummy_init_array_entry
      main_dynamic:000000000000214c r __FRAME_END__
      main_dynamic:0000000000003fb8 d _GLOBAL_OFFSET_TABLE_
      main_dynamic:                 w __gmon_start__
      main_dynamic:0000000000002004 r __GNU_EH_FRAME_HDR
      main_dynamic:0000000000001000 t _init
      main_dynamic:0000000000003db0 d __init_array_end
      main_dynamic:0000000000003da8 d __init_array_start
      main_dynamic:0000000000002000 R _IO_stdin_used
      main_dynamic:                 w _ITM_deregisterTMCloneTable
      main_dynamic:                 w _ITM_registerTMCloneTable
      main_dynamic:00000000000011d0 T __libc_csu_fini
      main_dynamic:0000000000001160 T __libc_csu_init
      main_dynamic:                 U __libc_start_main@@GLIBC_2.2.5
      main_dynamic:0000000000001149 T main
      main_dynamic:00000000000010c0 t register_tm_clones
      main_dynamic:0000000000001060 T _start
      main_dynamic:0000000000004010 D __TMC_END__
      main_dynamic:                 U myprint()
      
      发现不管是在目标文件还是可执行文件,myprint()都是未解析的符号错误(undefined reference),GPT说对于动态库是正常的。那拿静态库试一下
      [test_so_a] :) g++ -c myprint.cc -o myprint.o
      [test_so_a] :) ar rcs ./a/libmyprint.a myprint.o
      [test_so_a] :) g++ -o main_static -L ./a/ -lmyprint
      /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
      (.text+0x24): undefined reference to `main'
      collect2: error: ld returned 1 exit status
      [test_so_a] :( g++ -o main_static main_static.o -L ./a/ -lmyprint
      [test_so_a] :) ./main_static 
      myprint
      [test_so_a] :) nm -AC main_static.o
      main_static.o:                 U _GLOBAL_OFFSET_TABLE_
      main_static.o:0000000000000000 T main
      main_static.o:                 U myprint()
      [test_so_a] :) nm -AC main_static
      main_static:0000000000004010 B __bss_start
      main_static:0000000000004010 b completed.8061
      main_static:                 w __cxa_finalize@@GLIBC_2.2.5
      main_static:0000000000004000 D __data_start
      main_static:0000000000004000 W data_start
      main_static:0000000000001090 t deregister_tm_clones
      main_static:0000000000001100 t __do_global_dtors_aux
      main_static:0000000000003dc0 d __do_global_dtors_aux_fini_array_entry
      main_static:0000000000004008 D __dso_handle
      main_static:0000000000003dc8 d _DYNAMIC
      main_static:0000000000004010 D _edata
      main_static:0000000000004018 B _end
      main_static:00000000000011f8 T _fini
      main_static:0000000000001140 t frame_dummy
      main_static:0000000000003db8 d __frame_dummy_init_array_entry
      main_static:000000000000217c r __FRAME_END__
      main_static:0000000000003fb8 d _GLOBAL_OFFSET_TABLE_
      main_static:                 w __gmon_start__
      main_static:000000000000200c r __GNU_EH_FRAME_HDR
      main_static:0000000000001000 t _init
      main_static:0000000000003dc0 d __init_array_end
      main_static:0000000000003db8 d __init_array_start
      main_static:0000000000002000 R _IO_stdin_used
      main_static:                 w _ITM_deregisterTMCloneTable
      main_static:                 w _ITM_registerTMCloneTable
      main_static:00000000000011f0 T __libc_csu_fini
      main_static:0000000000001180 T __libc_csu_init
      main_static:                 U __libc_start_main@@GLIBC_2.2.5
      main_static:0000000000001149 T main
      main_static:                 U puts@@GLIBC_2.2.5
      main_static:00000000000010c0 t register_tm_clones
      main_static:0000000000001060 T _start
      main_static:0000000000004010 D __TMC_END__
      main_static:000000000000115d T myprint()
      [test_so_a] :) 
      
      发现main_static:000000000000115d T myprint()
    • 生成符号表
      其实上述已经为可执行文件main_dynamic和main_static生成了带有myprint的符号表,毕竟没有-L都无法生成文件。故不表。
    • 查看是否生成依赖信息
      [test_so_a] :( g++ -o main_dynamic main_dynamic.o
      /usr/bin/ld: main_dynamic.o: in function `main':
      main.cc:(.text+0x9): undefined reference to `myprint()'
      collect2: error: ld returned 1 exit status
      [test_so_a] :( g++ -o main_dynamic main_dynamic.o -L ./so -lmyprint
      [test_so_a] :) ldd main_dynamic 
              linux-vdso.so.1 (0x00007ffdb0769000)
              libmyprint.so => ./so/libmyprint.so (0x00007f0a63c44000)
              libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0a63a47000)
              /lib64/ld-linux-x86-64.so.2 (0x00007f0a63c50000)
      [test_so_a] :) 
      

第二个问题

  1. 环境变量LD_LIBRARY_PATH的作用?
    为可执行程序指定在运行时加载自定义动态库的搜索路径。对于标准库,其标准搜索路径是(这里不确定是不是这个命令):
    [test_so_a] :) ldconfig -v 2>/dev/null | grep -v ^$'\t'
    /usr/lib/x86_64-linux-gnu/libfakeroot:
    /usr/local/lib:
    /lib/x86_64-linux-gnu:
    /lib:
    [test_so_a] :) cpp -v /dev/null -o /dev/null
    Using built-in specs.
    COLLECT_GCC=cpp
    OFFLOAD_TARGET_NAMES=nvptx-none:hsa
    OFFLOAD_TARGET_DEFAULT=1
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.4.0-1ubuntu1~20.04.2' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-9-9QDOt0/gcc-9-9.4.0/debian/tmp-nvptx/usr,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
    Thread model: posix
    gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2) 
    COLLECT_GCC_OPTIONS='-E' '-v' '-o' '/dev/null' '-mtune=generic' '-march=x86-64'
     /usr/lib/gcc/x86_64-linux-gnu/9/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu /dev/null -o /dev/null -mtune=generic -march=x86-64 -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection
    ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
    ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/include-fixed"
    ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9/../../../../x86_64-linux-gnu/include"
    #include "..." search starts here:
    #include <...> search starts here:
     /usr/lib/gcc/x86_64-linux-gnu/9/include
     /usr/local/include
     /usr/include/x86_64-linux-gnu
     /usr/include
    End of search list.
    COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/
    LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9/../../../:/lib/:/usr/lib/
    COLLECT_GCC_OPTIONS='-E' '-v' '-o' '/dev/null' '-mtune=generic' '-march=x86-64'
    [test_so_a] :) 
    
    这里
    [test_so_a] :) echo $LD_LIBRARY_PATH
    
    [test_so_a] :) ./main_dynamic 
    ./main_dynamic: error while loading shared libraries: libmyprint.so: cannot open shared object file: No such file or directory
    [test_so_a] :( export LD_LIBRARY_PATH=./so/:${LD_LIBRARY_PATH}
    [test_so_a] :) ./main_dynamic 
    myprint
    [test_so_a] :) 
    
    参考https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dynamic_or_shared.html
    https://www.zhihu.com/question/537366949

为什么没用-I(大写的i)也可以?

  1. 参考

    You can specify any number or combination of these options on the command line to search for header files in several directories. The lookup order is as follows:
    For the quote form of the include directive, the directory of the current file is searched first.
    For the quote form of the include directive, the directories specified by -iquote options are searched in left-to-right order, as they appear on the command line.
    Directories specified with -I options are scanned in left-to-right order.
    Directories specified with -isystem options are scanned in left-to-right order.
    Standard system directories are scanned.
    Directories specified with -idirafter options are scanned in left-to-right order.
    参考
    https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html

相关文章:

  • 2025年Java面试题目收集整理归纳(持续更新)
  • 模板(初阶)
  • Java 浅拷贝和深拷贝
  • 【空间插值】地理加权回归模型(GWR, Geographically Weighted Regression)
  • Windows 发票闪印 PrintPDF-v3.6.10-第三方发票打印辅助工具,无需安装阅读器即可使用
  • 使用 ESP32 和 Python 进行手势识别
  • 蓝桥与力扣刷题(蓝桥 等差数列)
  • Word中把参考文献引用改为上标
  • Linux上位机开发实战(按钮响应)
  • AI绘画软件Stable Diffusion详解教程(10):图生图进阶篇(局部手绘修正)
  • Python 正则表达式模块 re
  • 「基于大模型的智能客服系统」语义理解、上下文记忆与反馈机制设计
  • 实现悬浮按钮拖动,兼容h5和微信小程序
  • LinPEAS 使用最佳实践指南
  • Profinet转Profinet以创新网关模块为核心搭建西门子和欧姆龙PLC稳定通讯架构案例​
  • 中级软件设计师2004-2024软考真题合集下载
  • 【每日学点HarmonyOS Next知识】嵌套组件、装饰器报错、迭代列表刷新、单位换算、tabs组件生命周期
  • 使用GPTQ量化Llama-3-8B大模型
  • stm32F103RCT6+ModBus之RTU
  • SpringBoot学生宿舍管理系统的设计与开发
  • 有网站是做水果原产地代发的吗/全球疫情最新消息
  • 做flash网站/简述什么是网络营销