用了很久的编译器,在编译新的源程序时,其中一个动态链接库.so文件,忽然报undefined symbol错。很是奇怪。于是,查之。

首先报错的symbol是C++ name mangling(为了防止重名,对程序中名称做特殊处理)之后的,C++filt转换之后,把符号名在源码中grep了一把,发现是个函数名。这个函数名定义如下:

inline fun_name() {
...
}

在另外一个文件中有对该函数的引用,于是有这个声明: extern inline fun_name().问题就出在这个extern inline上。
标记了inline的函数可以接着标记extern吗?
什么是inline,一个函数被标记为inline之后,编译器就会在该函数的被调用点,使用函数体替代调用点。参数采取重命名的方式来防止变量名冲突。这样避免了函数调用的开销,能提升性能,但同时会增加可执行程序的大小。
什么是extern, extern 告诉编译器,某个函数/变量的定义可能在其他的C++源码文件中,编译器在编译时,就直接生成一个函数调用点,只在链接时在其他文件中查找该函数/变量的定义。
两个能同时用于定义一个函数吗?能,但是不同的编译器处理方式不同,在MAC OS系统下,IBM XL C/C++编译器中,若该函数声明在头文件里,就直接视为extern声明。而在gnu 编译器中,则直接视为inline声明。 “extern inline“在C++的标准里没有定义,所以各个编译器如何实现都不同。最好不要这么用。

因为inline是为了性能,所以去掉inline关键字后,这个bug也就过了。

教训就是:写程序一定要有标准,编译器不好做。是是非非不好衡量。还得有标准才行。
参考:

  1. http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=/com.ibm.vacpp6m.doc/language/ref/clrc07cplr243.htm
  2. http://www.greenend.org.uk/rjk/2003/03/inline.html
  3. http://stackoverflow.com/questions/216510/extern-inline

相关文章:

  5 Responses to “extern inline问题”

  1. 额,还有一种雷人的做法,C++里面头文件中类的类型定义部分用上inline,但是却不写上函数体,而是在源文件中加上。有的GCC能过,有的不行,但是过了都能正常跑,可能是编译器不严格吧。从语言的结构上来说,这个或许也是一种extern inline

    • 我觉得要是真的做到编译器能标准处理这种extern inline问题,不会出现有的版本gcc能过,有的不能过,还是得靠理论上严格的形式验证。这个有难度。。。。

  2. 忘了从哪里看到,好像说函数的inline只能是在编译时,而不在链接时。

    感觉inline修饰符的函数可以当作带类型的宏,若要在多个文件里面使用这个函数,比较保险的方法可以再在前面加个static,放到头文件里面。像这样:

    xx.h //both included by a.c and b.c
    static inline fun_name() {

    }

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

   
2009-2011© 编译点滴 Suffusion theme by Sayontan Sinha

无觅相关文章插件,快速提升流量