c++使用 inline成员函数制作静态库的坑点
关于inline对链接时的影响
问题:
在分别编译以下代码成目标文件,然后链接成静态库(.a)报错undefined reference..
iusk@wgnmd:~/Documents/Bitusk/testing$ g++ -static testError.o ../src/Error.o
/usr/bin/ld: testError.o: in function `main':
testError.cpp:(.text+0x2b): undefined reference to `ErrorCatcher::invalidHashError[abi:cxx11]()'
collect2: error: ld returned 1 exit status
//File: include/Error.h
class ErrorCatcher{
public:
static const std::string invalidFd();
};
//File: src/Error.cpp
inline const std::string ErrorCatcher::invalidFd() {
return "INVALIDFD";
}
//File: testing/testError.cpp
#include "Error.h"
int main(int argc, char* argv[]) {
std::cout<<ErrorCatcher::invalidFd()<<std::endl;
return 0;
}
认真排除了常见的undefined ref的常见错误都没问题[^其余常见问题可见Ref.],使用nm查看.o文件的函数符号发现并没有testError.o 所需要符号。如下所示:
iusk@wgnmd:~/Documents/Bitusk/testing$ nm -C testError.o
//省略不必要的符号...
0000000000000280 t __static_initialization_and_destruction_0(int, int)
U ErrorCatcher::invalidFd[abi:cxx11]()
//......
nm的详细使用可参照[^2]
iusk@wgnmd:~/Documents/Bitusk/src$ nm -CA *.o
BtError.o:0000000000000000 r std::piecewise_construct
由此可见编译器直接inline了所以定义的static member func,symbol table中没有所需要的符号,自然ld(链接器)不能找到所需要的符号,也就报错了。这是一个很微妙的问题。将.o文件归档为libmy.a链接时也会出现同样的报错。
解决办法:
在库文件(.a)中,对外提供symbol的函数不能inline。inline函数的定义最好放在.h文件中。因为不同的编译器对inline的要求也是不一样。有些地方inline,有些不inline。
背后机制:
inline是在编译时把代码嵌入到调用函数里面,并不会有额外函数调用的负担。所以编译的时候必须要能够看到完整的定义。在静态库中是会有inline的函数,但是在对外的API中是不会有的。在动态库中也亦是如此。
Ref.
[1] htt"undefined reference to XXX"问题总结
[2] linux下强大的文件分析工具 -- nm
[3] Linux下Gcc编译链接静态库&动态库
[4] Shared Libraries With GCC on linux
[5] Definitions And ODR(one definition rule)
[6] static inline vs inline vs static in C++
[7] C/C++ Include Guidelines
[8] 多态与虚拟

浙公网安备 33010602011771号