C++ inline weak symbol and so on
关于inline这个关键字,听到强调得最多的是,它只是一种对于编译器的建议,而非强制执行的限定。
但事实上,即使这个优化最终由于函数太过复杂的原因没有达成,加上inline关键字(还有在类定义中直接定义的函数也相当于加上了inline关键字)还是会带来一些区别的。
参看C++11标准文档里面的描述:
A function declaration (8.3.5, 9.3, 11.3) with an inline specifier declares an inline function. The inline
specifier indicates to the implementation that inline substitution of the function body at the point of call
is to be preferred to the usual function call mechanism. An implementation is not required to perform this
inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules
for inline functions defined by 7.1.2 shall still be respected.
这里所谓的other rules具体如下:
An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly
the same definition in every case (3.2). [ Note: A call to the inline function may be encountered before its
definition appears in the translation unit. — end note ] If the definition of a function appears in a translation
unit before its first declaration as inline, the program is ill-formed. If a function with external linkage is
declared inline in one translation unit, it shall be declared inline in all translation units in which it appears;
no diagnostic is required. An inline function with external linkage shall have the same address in all
translation units. A static local variable in an extern inline function always refers to the same object.
A string literal in the body of an extern inline function is the same object in different translation units.
[ Note: A string literal appearing in a default argument is not in the body of an inline function merely
because the expression is used in a function call from that inline function. — end note ] A type defined
within the body of an extern inline function is the same type in every translation unit.
这里最关键的就是一个内联的函数,可以在多个cpp文件里面都有定义(回想一下普通函数如果这么干的话会有multiple definition的错误),标准明确了多个cpp文件的定义一定要一致,
但是编译器层面并不检查。
要理解An inline function with external linkage shall have the same address in all translation units. 这句话,可能需要对于链接过程有一定的理解。(深入理解计算机系统(csapp)第7章)。还可以看一下http://blog.copton.net/articles/linker/
这里简单表述就是,C++程序的每一个编译单元(cpp文件),编译完成之后生成一个.o文件,链接过程就是将这些.o文件合成一个可执行文件。
.o文件里是哪些内容呢?很多,关心的主要是以下几项
.text:代码段,包括这个cpp文件里定义的所有函数得到的字节码
.data:全局已初始化数据
.bss:全局未初始化数据
.reltext:引用的外部函数符号(比如我们会在引用外部函数或变量的时候有一个声明)
.reldata引用的外部变量
合成过程需要将各个.o文件的这几个部分聚合到一起:1重定位,聚合之后变量、函数都要重新排布,当然需要重定位2、将.reltext .data节里引用的外部函数,变量等赋予最终重定位之后的地址
看到这里,就能够大概理解,如果两个cpp文件恰好定义了同一个函数,会造成它们生成的.o文件在聚合的时候不知道取哪个定义,那么其它引用这个函数的地方也不知道重定位到哪,
所以会出现multiple definition的错误。而根据上面对于inline内联函数的表述,可以发现,它事实上赋予这种函数一个特别的属性,就是在多个.o文件里都定义了同一个内联函数的时候,
(这里当然不是成功内联的情形,因为那样的话根本只是插入代码段,连函数符号都没有了,更不用担心重定义了),链接器确保只从中选取一个作为最终的符号地址,这样就保证了
不会由重定义的情况出现了。
C++ inline weak symbol and so on的更多相关文章
- GNU的strong symbol和weak symbol
首先,同样的原型的两个函数在连个不同的c文件中都有定义,把这两个c文件编译.连接在一起,也没有什么错误.原因就是因为,gcc中有一个strong symbol和weak symbol的概念.默认函数定 ...
- [原] inline operator delete & DLL boundary
很久以前写在百度空间的这篇文章: [百度空间] [原] 全局operator delete重载到DLL 首先,纠正一个词“重载”,operator new/delete是替换(replacement) ...
- gcc/g++中weak弱符号及alias别名
最近查看linux内核代码时,表现了一些编译器选项如__attribute_((weak)).__attribute__( (alias("target"))),一开始不了解,后来 ...
- C语言之强化,弱化符号weak
一.概述 在C语言中,函数和初始化的全局变量(包括显示初始化为0)是强符号,未初始化的全局变量是弱符号. 对于它们,下列三条规则使用: ① 同名的强符号只能有一个,否则编译器报"重复定义&q ...
- weak alias
Weak Alias 跟 Weak Reference 完全没有任何关系,不过是我在看到 Weak Reference 的时候想到的而已. Weak Alias 是 gcc 扩展里的东西,实际上是函数 ...
- 弱符号__attribute__((weak))
弱符号是什么? 弱符号: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误.链接器会忽略弱符号,去使用普通的全局符号 ...
- __attribute__((weak, alias())))
参考gcc的reference: 弱符号: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误.链接器会忽略弱符号,去 ...
- 5.24 Declaring Attributes of Functions【转】
转自:https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Function-Attributes.html 5.24 Declaring Attributes o ...
- GNU C/C++ __attributes__ GCC中的弱符号与强符号
最近在看一些源代码,遇到了一些使用__attribute__修饰函数和变量的属性方面的代码,不是太了解,很是汗颜,再此做个总结: GCC使用__attribute__关键字来描述函数,变量和数据类 ...
随机推荐
- echarts饼图--数据交互
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- nodeschool.io 8
~~ HTTP COLLECT ~~ Write a program that performs an HTTP GET request to a URL provided toyou as the ...
- hdu 3908 Triple(组合计数、容斥原理)
Triple Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 125536/65536 K (Java/Others) Total Su ...
- 张艾迪(创始人):DCM的不识人.我说我会像乔布斯一样成为投资者的骄傲
Eidyzhang解码:天才Eidyzhang的诞生 张艾迪(创始人):第一个实习生精英团队 张艾迪(创始人):DCM的不识人.我说我会像乔布斯一样成为投资者的骄傲 2014-05-31 09:4 ...
- Git删除远程分支
查看 git branch -a 删除远程分支 git branch -r -d origin/branch-name //只是删除的本地对该远程分支的track git push origin : ...
- SQL Server 一列或多列重复数据的查询,删除
业务需求 最近给公司做一个小工具,把某个数据库(数据源)的数据导进另一个数据(目标数据库).要求导入目标数据库的数据不能出现重复.但情况是数据源本身就有重复的数据.所以要先清除数据源数据. 于是就把关 ...
- 最小生成树练习3(普里姆算法Prim)
风萧萧兮易水寒,壮士要去敲代码.本女子开学后再敲了.. poj1258 Agri-Net(最小生成树)水题. #include<cstdio> #include<cstring> ...
- VS构建工具介绍
VS构建工具介绍 我们都知道C/C++源代码要生成可执行的.exe程序,需要经过编译.链接的过程.你在VS工具中只需要选择菜单Build或按一下F5可以编译.链接.运行了,其实IDE帮我隐藏了好多的具 ...
- 使用Join代替In
我们知道,在sql中使用IN让我们的where子句可以规定多个值.当需要从一个集合中查询包含某几个值的记录的时候,通常我们会选择使用IN来实现,其实,使用JOIN也可以实现这样的功能,而且性能要比IN ...
- ace-下载-安装
安装ACE 1.获取安装包 到ACE的官方网站http://www.cs.wustl.edu/~schmidt/ACE.html或者http://riverace.com/index.htm下载最新版 ...