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__关键字来描述函数,变量和数据类 ...
随机推荐
- .NET简谈反射(动态调用)
我们继续C#基础知识的学习,这篇文章主要要讲的是我们C#程序员迈向高级C#程序员的关键性的一步. 有的朋友会说事实不是这样的,我不用反射就不能开发吗?当然可以,但是用与不用肯定是不一样的,任何复杂抽象 ...
- SyntaxError: Non-ASCII character '\xe7' in file解决方法
SyntaxError: Non-ASCII character '\xe7' in file 出现这种错误的原因是程序中的编码出问题了,只要在程序的最前面加上 最前面的意思是在最前面,包括在注释的前 ...
- Java线程与多线程教程
本文由 ImportNew - liken 翻译自 Journaldev. Java线程是执行某些任务的轻量级进程.Java通过Thread类提供多线程支持,应用可以创建并发执行的多个线程. 应用 ...
- MyBatis实体类映射文件模板
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC " ...
- translatesAutoresizingMaskIntoConstraints
如果是从代码层面开始使用Autolayout,需要对使用的View的translatesAutoresizingMaskIntoConstraints的属性设置为NO,即可开始通过代码添加Constr ...
- OC 类别(分类)Categroy
Categroy类别,又称为扩展类,在类的原基础上扩展方法,且不可添加变量,如果扩展的方法与原始类中的方法相同,则会隐藏原始方法,且不可在扩展方法中通过super调用原始方法,这里与继承不同. 定义: ...
- [转]Java8-本地缓存
这里我将会给大家演示用ConcurrentHashMap类和lambda表达式实现一个本地缓存.因为Map有一个新的方法可以在key为Null的时候自动计算一个新的value值.非常完美的实现cach ...
- 网站开发中必备的8个 jQuery 效果【附源码】
jQuery 作为最优秀 JavaScript 库之一,改变了很多人编写 JavaScript 的方式.它简化了 HTML 文档遍历,事件处理,动画和 Ajax 交互,而且有成千上万的成熟 jQuer ...
- [转]C#设置WinForm快捷键
1.Alt+*(按钮快捷键)按钮快捷键也为最常用快捷键,其设置也故为简单.在大家给button.label.menuStrip等其他控件的Text属性指定名称时,在其后面加上‘&’然后在加上一 ...
- li排序的两种方法
1.一般做法 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <ti ...