有三个工程文件,A为SDL2动态库,B为基于A的静态库,C为基于A和B的主程序EXE,现在发现这个问题:
在C程序链接器命令的时候,通常像这种写法-lSDL2 -lLibB,此时就会报B报错找不到A中的函数,但是如果交换顺序-lLibB -lSDL2就正常了,这是为何?
这是由于链接器的工作方式导致的,主要涉及到静态库和动态库之间的依赖顺序问题。
链接器的解析顺序
链接器在解析库时是 从左到右 的顺序工作的。当它遇到一个库时,它会试图从这个库中解析之前遇到但未解析的符号。这意味着,如果某个库需要依赖另一个库中的符号,这两个库在链接命令中的顺序至关重要。
链接顺序问题的解释
当你使用 -lSDL2 -lLibB 时:
链接器首先遇到 -lSDL2,但此时没有未解析的符号需要解析。
接下来遇到 -lLibB,其中包含了对 SDL2 库的函数调用,但由于链接器已经经过了 SDL2 库,且没有记录下来这些未解析的符号,所以此时 LibB 无法解析这些函数,导致报错。
当你使用 -lLibB -lSDL2 时:
链接器首先遇到 -lLibB,其中包含了对 SDL2 中函数的调用,但这些符号尚未解析,链接器将它们标记为待解析。
接下来遇到 -lSDL2,此时链接器可以解析之前 LibB 中未解析的 SDL2 函数,从而解决所有符号的依赖,链接成功。
关键点
从左到右解析:链接器在处理库时是从左到右的,所以当它遇到一个库时,只会解析已经遇到的未解析符号。如果某个库依赖另一个库中的符号,那个被依赖的库必须在依赖库之后列出。
静态库与动态库:静态库(LibB)中未解析的符号需要动态库(SDL2)提供,而链接器只会在遇到这些未解析符号后继续寻找它们的定义。因此,SDL2 必须在 LibB 之后列出,以确保 LibB 中的未解析符号能够被 SDL2 解析。
解决方法
保持 -lLibB -lSDL2 的顺序,确保静态库 LibB 依赖的 SDL2 动态库在其之后进行链接。
总结
链接器从左到右依次处理库,因此需要将被依赖的库(如 SDL2)放在依赖库(如 LibB)的后面,以确保符号能够被正确解析。这就是为什么 -lLibB -lSDL2 正常,而 -lSDL2 -lLibB 会导致 LibB 无法找到 SDL2 中的符号的原因。