gcc链接选项--export-dynamic的一次问题记录

背景:

BS进程cli动态获取与修改需要用到延迟加载库的一组dlopen API,主要用到这三组API:dlopen()、dlerror()、dlclose。详细的接口说明参考man手册或者《Linux/Unix系统编程手册》。

bs进程调用了上面介绍的这三组API,为了实现在调用libaccBalConfigEscapes.so.1.0.0处理cli命令的时候能回调bs主程序的UpdatAccBalInfo与GetAccBalInfo函数:

void UpdatAccBalInfo(const BS::OperAccBal &operType, const BS::AccCfgMsg &msg)

{

InfoLog("cll", " UpdatAccBalInfo");

g_BSApp.AccBalChangedHandler(operType, msg);

}

void GetAccBalInfo(std::map<std::string, BS::SubInfo> &m_subInfoMap)

{

InfoLog("cll", " GetAccBalInfo");

g_BSApp.GetAccBal(m_subInfoMap);

}

将这两个函数声明为全局函数:

extern void UpdatAccBalInfo(const BS::OperAccBal &operType, const BS::AccCfgMsg &msg);

extern void GetAccBalInfo(std::map<std::string, BS::SubInfo> &m_subInfoMap);

在libaccBalConfigEscapes.so.1.0.0源文件里面用,引用包含以上两个函数声明的头文件。

简而言之:就是在库文件里面仅仅是声明某个函数,该函数的具体实现在调用库的主程序里面完成,这样当调用库中的某个函数的时候,实际上这个被调用函数的实现是用户自己实现的,实现类似于回调的机制。

问题:

这里存在的问题是,用bjam编译出来的bs进程在运行时候会报错:

./bs: symbol lookup error: /usr/local/escapes/libaccBalConfigEscapes.so.1.0.0: undefined symbol: _Z15UpdatAccBalInfoRKN2BS10OperAccBalERKNS_9AccCfgMsgE

./bs: symbol lookup error: /usr/local/escapes/libaccBalConfigEscapes.so.1.0.0: undefined symbol: _Z13GetAccBalInfoRSt3mapISsN2BS7SubInfoESt4lessISsESaISt4pairIKSsS1_EEE

提示找不到这两个符号,c++为了实现函数重载、名称空间等机制函数符号是不可读的。可以用c++filter转换成可读格式:

可见这两个符号指向的函数就是我们声明的全局函数!为什么找不到呢?

解决:

换编译环境,用基于makefile的gb编译,运行时候没有报错。因为编译器版本都是libgcc-4.4.7-4.el6.i686,怀疑应该是gb的makefile和bjam的jamroot在gcc选项设置上有区别导致的找不到全局符号。

查看gb的makefile有如下内容:

关键的不同是:-Wl,--export-dynamic –pthread

-Wl:指示后面的选项是给链接器的

-pthread: 链接程序的时包含libpthread.so

--export-dynamic:就是这个选项让主程序内定义的全局函数对库函数可见。

找到原因,修改jamroot增加如下几行:

也可以这么加:

<linkflags>-export-dynamic或

<linkflags>-Wl,-export-dynamic或

<linkflags>-Wl,--export-dynamic 或

但不能这么加:

<linkflags>--export-dynamic

<cxxflags>--export-dynamic

<cxxflags>-export-dynamic

<cxxflags>-Wl,--export-dynamic

<cxxflags>-Wl,-export-dynamic

重新编译bs进程,运行,找到符号。问题解决。

小结:

没看明白?举个栗子:

prog.cpp:

foo.h:

注:这里extern “C”是必须得,否则c++特有的函数符号规则不是dlsym的参数“fun2”

foo.cpp:

编译测试:

失败:

[cll@localhost sharedlib]$ g++ -g -fPIC foo.cpp -shared -o libfoo.so

[cll@localhost sharedlib]$ g++ -ldl prog.cpp -o prog

[cll@localhost sharedlib]$ ./prog

./prog: symbol lookup error: ./libfoo.so: undefined symbol: _Z4fun1v

成功:

[cll@localhost sharedlib]$ g++ -g -fPIC foo.cpp -shared -o libfoo.so

[cll@localhost sharedlib]$ g++ -Wl,--export-dynamic -ldl prog.cpp -o prog

[cll@localhost sharedlib]$ ./prog

INFO: i am fun1

结果显而易见。--export-dynamic参数如果不知道什么意思,很容易被忽略,也只有在这种类似回调的机制里才会显示出不可缺少的价值。

更多原创技术分享 搜索公众号 柠檬的编程学堂
公众号

发布了23 篇原创文章 · 获赞 7 · 访问量 9875

猜你喜欢

转载自blog.csdn.net/u011644231/article/details/88880362