C++命名空间中操作符函数的动态链接问题

最近用g++编译和链接共享库时,发现一个命名空间中操作符函数导出的问题。

 

过程是这样的:程序中有些C++操作符函数,放在命名空间中,这些函数需要作为共享库供其他程序调用。

例如,函数声明如下:

#mylib.h namespace myns { //.... ACE_CDR::Boolean operator<< (ACE_OutputCDR& os, PDCommand& x); //.... }

       函数实现如下:

#mylib.cpp #include "mylib.h" using namespace myns; ACE_CDR::Boolean operator<< (ACE_OutputCDR& os, PDCommand& x) { //... }

共享库本身的编译和链接没有问题,但其他程序与共享库链接时,提示找不到声明对应的符号引用:

"undefined reference to `myns::operator<<(ACE_OutputCDR&, myns::PDCommand&)'"。

用nm查看共享库:

nm libmy.so | grep PDCommand

发现两个符号

                              U _ZN2mynslsER13ACE_OutputCDRRNS_9PDCommandE
000000000000f3f2 T _ZlsR13ACE_OutputCDRRN2myns9PDCommand
仔细观察发现,第一个符号相当于:

myns::operator << (ACE_OutputCDR& os, myns::PDCommand& x);

第二个符号相当于:

operator << (ACE_OutputCDR& os, myns::PDCommand& x);

另外,nm的输出中,"U"表示符号未定义,“T”表示代码段(TEXT段)。

因此,我们可以推断出第一条记录是在.h文件中导出的,第二条记录是在.cpp文件中导出的。由于两者的命名空间不同,导致头文件中声明的函数没有相应的定义,进而导致外部程序链接时失败。

 

如果把cpp文件中的函数实现改为如下,可以解决问题:

#mylib.cpp #include "mylib.h" namespace myns { //... ACE_CDR::Boolean operator<< (ACE_OutputCDR& os, PDCommand& x) { //... } } //namespace myns

此时再用nm查看共享库中的导出符号,发现只有一条记录:

000000000000f332 T _ZN2mynslsER13ACE_OutputCDRRNS_9PDCommandE

即相当于:

myns::operator << (ACE_OutputCDR& os, myns::PDCommand& x);

这正是我们想要的。

 

以上问题是由于“using namespace xxx”这种写法是一种不精确的命名空间指定,有可能出现起义。不过,对于命名空间中的非操作符函数的导出和链接,我还没有发现类似问题。

 

因此,目前可以得出,在共享库中导出有命名空间的c++操作符函数时,其实现文件中最好显式指定函数的命名空间,而不要用“using namespace xxx”的形式。

你可能感兴趣的:(Unix/Linux操作系统,C/C++编程,c++,reference,os,c)