今天發現一個問題,與inline
有關,也與編譯時候是不是優化有關。
大概問題可以用下面的代碼來描述:
先寫一個libtest1
,代碼如下
libtest1.h
#ifndef LIBTEST_H
#define LIBTEST_H
class Test{
public:
inline void fun1()const;
void fun2()const;
};
#endif //!LIBTEST_H
libtest1.cpp
#include <stdio.h>
#include "libtest.h"
void Test::fun1()const
{
puts("fun1");
}
void Test::fun2()const
{
fun1();
puts("fun2 call fun1");
}
編譯為動態庫,使用命令為:gcc -shared -fpic libtest.cpp -o libtest1.so
然后第二個動態庫libtest2
,代碼如下
#include "libtest.h"
extern "C" void fun3()
{
Test t;
t.fun1();
t.fun2();
}
編譯命令為:gcc -shared -fpic libtest2.cpp -o libtest2.so -Wl,-rpath=. -L. -ltest1
然后寫測試代碼,運行時加載libtest2.so
,然后調用fun3
函數。代碼如下
#include <stdio.h>
#include <dlfcn.h>
typedef void (FuncType)();
int main()
{
//void* p = dlopen("./libtest2.so",RTLD_NOW);
void* p = dlopen("./libtest2.so",RTLD_LAZY);
if(p == NULL){
printf("dlopen libtest2.so failed:%s\n",dlerror());
return 0;
}
FuncType* f1 = (FuncType*)dlsym(p,"fun3");
if(f1 == NULL){
printf("dlsym fun3 failed:%s\n",dlerror());
return 0;
}
f1();
dlclose(p);
return 0;
}
編譯執行結果如下:
/home/o/sopath [o@o-pc] [13:40]
> gcc test.cpp -o test -ldl
/home/o/sopath [o@o-pc] [13:41]
> ./test
fun1
fun1
fun2 call fun1
看起來好像沒有問題,但是這里編譯的時候都沒有進行優化,使用的默認選項,如果我們編譯命令修改一下,則就變了
/home/o/sopath [o@o-pc] [13:34]
> gcc -shared -fpic libtest.cpp -o libtest.so -O3
/home/o/sopath [o@o-pc] [13:41]
> ./test
./test: symbol lookup error: ./libtest2.so: undefined symbol: _ZNK4Test4fun1Ev
這時候就找不到fun1
這個函數了,使用strings libtest1.so
也確實找不到。但是如果把fun1前面的inline
去掉,就沒有問題了。