文章目录
-
- 问题
- 环境
- 文件逻辑
- 动态编译
-
- 编译成动态库
- 使用g++链接
- 使用clang++链接
- 静态链接
-
- 编译成静态库
- 使用g++链接
- 使用clang++链接同g++。
- 结论
问题
讨论了一下动态链接和静态链接的问题,即在链接过程中到底是以什么顺序进行链接的,中间会不会保存一部分信息到符号表中。
环境
Ubuntu 14.04.6 LTS
g++ (Ubuntu 5.5.0-12ubuntu1~14.04) 5.5.0 20171010
Ubuntu clang version 3.4-1ubuntu3
文件逻辑
main.cc调用test.cc,test.cc调用test2.cc
// main.cc
#include "test.h"
int main()
{
test();
return 0;
}
// test.cc
#include "test2.h"
void test()
{
test2();
}
// test2.cc
#include <iostream>
using namespace std;
void test2()
{
cout << "test2" << endl;
}
动态编译
编译成动态库
g++ test.cc -shared -fPIC -o libtest.so
g++ test2.cc -shared -fPIC -o libtest2.so
使用g++链接
g++ main.cc -o main -L./ -ltest -ltest2 -I./
g++ main.cc -o main -L./ -ltest2 -ltest -I./
第一条语句报错
.//libtest.so: undefined reference to `test2()’
collect2: error: ld returned 1 exit status
第二条语句链接成功
使用clang++链接
clang++ main.cc -o main -L./ -ltest -ltest2 -I./
clang++ main.cc -o main -L./ -ltest2 -ltest -I./
两条语句均可正常链接
静态链接
编译成静态库
g++ -c test.cc
g++ -c test2.cc
ar -rc test.a test.o
ar -rc test2.a test2.o
使用g++链接
g++ main.cc test.a test2.a -o main
g++ main.cc test2.a test.a -o main
第一条语句正常执行
第二条语句报错
test.a(test.o): In function
test()': test.cc:(.text+0x5): undefined reference to
test2()’
collect2: error: ld returned 1 exit status
使用clang++链接同g++。
结论
网上那些文章不靠谱哇。
g++不论是静态链接还是动态链接,都需要以正确的顺序进行链接,即基础类放在最右面。原理应该是g++从左向右扫描所有链接库,遇到链接库中不认识的符号就放在一个undefined表中,如果在后面的库中发现这个符号就填上正确的位置,没发现则最后链接报错。
clang++动态链接过程中会自动识别链接的顺序,静态链接需要手动调整顺序。