C++中弱符号(弱引用)的意义及实例
今天读别人代码时看到一个“#pragma weak”,一时没明白,上网研究了一个下午终于稍微了解了一点C、C++中的“弱符号”,下面是我的理解,不正确的地方望大家指正。
本文主要从下面三个方面讲“弱符号”:
1. 什么是“弱符号”? 它与“强符号”的区别是什么?
2. 弱符号的有什么作用?
3. 弱符号的实际应用实例
1.什么是弱符号?
在WikiPedia中弱符号的定义是:
a weak symbol is a symbol definition in an object file or dynamic library that may be overridden by other symbol definitions
A weak symbol denotes a specially annotated symbol during linking of Executable and Linkable Format (ELF) object files.
By default, without any annotation, a symbol in an object file is strong.
During linking, a strong symbol can override a weak symbol of the same name.
In contrast, two strong symbols that share a name yield a link error during link-time.
When linking a binary executable, a weakly declared symbol does not need a definition.
In comparison, (by default) a declared strong symbol without a definition triggers an undefined symbol link error.
Weak symbols are not mentioned by C or C++ language standards; as such, inserting them into code is not very portable.
Even if two platforms support the same or similar syntax for marking symbols as weak,
the semantics may differ in subtle points, e.g. whether weak symbols during dynamic linking at runtime lose their semantics or not
从第一个定义可以知道,“弱符号“是在一个文件或者动态库中定义的,可以被其他地方定义的符号overridden的符号。这里重点是“overridden”
从第二个定义,我们可以知道“弱符号”跟强符号主要有如下区别:
1. 弱符号可以只有申明,没有定义,强符号必须有定义
2. 弱符号可以定义多次,强符号只能定义。
另外第二个定义中还提到,弱符号并不是C、C++规范中的内容,这个跟编译器相关,不可移植。
在中文的很多文章中把weak symbol分为了两种“弱符号”(变量)“弱引用”(函数),但WikiPedia中弱符号的例子都是用的函数。
2.弱符号的作用
我的理解“弱符号变量“是C中遗留下来的,它除了引起麻烦,没有什么作用。C语言中凡是没有初始化的全局变量都是弱符号变量,如果存在多个同名的弱符号变量,编译器在链接时可以任意选一个(有的编译器选择占用空间最大的那个定义)。这样,你的代码中定义了一个x,忘了初始化,而你用到的某个库中又刚好定义了一个未初始化的x,后果大家可以自己想。C++中不会出现这个问题,因为C++中所有未初始化的全局变量都初始化为0。
弱符号函数的主要作用是为了多态,即使用定义中的”overridden“,一般在库中使用得比较多,比如你在你的库中为某个函数提供一个默认实现,用户如果想定制化的话可以自己实现一个。
例子:在library_foo.h中什么函数foo为弱符号函数,library_foo.cc中为foo提供一个默认实现,在my_foo.cc中为foo提供一个定制化的实现。
注:定义一个函数为弱函数有两种方式
1. 使用“#pragma week function”
2. 函数后面加“ __attribute__((weak))”,
我用的gcc好像不支持第一种方式。
//library_foo.h #ifndef __LIBRARY_FOO_H__
#define __LIBRARY_FOO_H__ void foo() __attribute__((weak));
void f(); #endif
//library_foo.cc #include <iostream>
#include "library_foo.h" void foo(){
std::cout<<"default foo"<<std::endl;
} void f(){
foo();
}
//main.cc #include <iostream>
#include "library_foo.h" using namespace std; int main(int argc, char* argv[]){
f();
}
//my_foo.cc
#include <iostream>
void foo(){
std::cout<<"My customized foo"<<std::endl;
}
编译及运行结果如下:
> g++ library_foo.cc main.cc my_foo.cc -o customized.x
> g++ library_foo.cc main.cc -o not_customized.x
> ./customized.x
my customized foo
> ./not_customized.x
default foo
可以看到,当链接my_foo.cc是,使用的是定制的foo.
3. 弱符号的实际应用实例
在C++库中,如下函数都是弱符号函数
void *operator new(std::size_t);
void *operator new(std::size_t, std::nothrow_t const &) noexcept;
void *operator new[](std::size_t);
void *operator new[](std::size_t, const std::nothrow_t&) noexcept;
void operator delete(void *) noexcept;
void operator delete(void *, std::nothrow_t const &) noexcept;
void operator delete[](void *) noexcept;
void operator delete[](void *, std::nothrow_t const &) noexcept;
C++中弱符号(弱引用)的意义及实例的更多相关文章
- C语言中的弱符号(weak)用法及实例
一 符号概念: 在C语言中,有强符号和弱符号,符号简单来说就是函数.变量的名字,对于全局(非局部.非static)的函数和变量,能不能重名是有一定规矩的,强.弱符号就是针对这些全局函数和变量来说的. ...
- 嵌入式C语言自我修养 09:链接过程中的强符号和弱符号
9.1 属性声明:weak GNU C 通过 __atttribute__ 声明weak属性,可以将一个强符号转换为弱符号. 使用方法如下. void __attribute__((weak)) fu ...
- 关于C语言中的强符号、弱符号、强引用和弱引用的一些陋见,欢迎指正
首先我表示很悲剧,在看<程序员的自我修养--链接.装载与库>之前我竟不知道C有强符号.弱符号.强引用和弱引用.在看到3.5.5节弱符号和强符号时,我感觉有些困惑,所以写下此篇,希望能和同样 ...
- 浅谈C语言中的强符号、弱符号、强引用和弱引用
摘自http://www.jb51.net/article/56924.htm 浅谈C语言中的强符号.弱符号.强引用和弱引用 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2014- ...
- 浅谈C语言中的强符号、弱符号、强引用和弱引用【转】
转自:http://www.jb51.net/article/56924.htm 首先我表示很悲剧,在看<程序员的自我修养--链接.装载与库>之前我竟不知道C有强符号.弱符号.强引用和弱引 ...
- GCC中的强符号和弱符号及强引用和弱引用
1. 强符号和弱符号 1.1 u-boot和kernel中的__weak指令 u-boot和kernel比较普遍地使用了__weak来定义函数. 在include\linux\compiler-gcc ...
- C语言中的强符号与弱符号
转自:http://blog.csdn.net/astrotycoon/article/details/8008629 一.概述 在C语言中,函数和初始化的全局变量(包括显示初始化为0)是强符号,未初 ...
- gcc/g++中weak弱符号及alias别名
最近查看linux内核代码时,表现了一些编译器选项如__attribute_((weak)).__attribute__( (alias("target"))),一开始不了解,后来 ...
- GNU C/C++ __attributes__ GCC中的弱符号与强符号
最近在看一些源代码,遇到了一些使用__attribute__修饰函数和变量的属性方面的代码,不是太了解,很是汗颜,再此做个总结: GCC使用__attribute__关键字来描述函数,变量和数据类 ...
随机推荐
- 总结swift语言常见的20个问题和回答
1.假设我是个刚入门的iOS开发人员,选swift学习呢,还是选objective-c学习,还是两个都学? 这个能够依据两种情况来决定:1.我想进入公司担任iOS开发的职位 2.我仅仅想做个独立 ...
- sqrt 源代码
stap -v -e 'probe process("/usr/local/mysql56/bin/mysqld").function("*@/usr/src/mysql ...
- Java基础知识强化之IO流笔记56:IO流练习之 登录注册IO版
1. 登录注册IO版的Java项目框架,如下: 2. 具体代码实现: (1)User.java(cn.itcast.game): package cn.itcast.pojo; /** * 这是用户 ...
- Manually connecting to the Oracle Linux Yum Server
Manually connecting to the Oracle Linux Yum Server 1. Download and Install Oracle Linux Note: The ...
- Linux基础(二)
二.Linux 常用命令 一.命令行操作的流程 录入命令(可以使用各种途径来发送命令) 命令被解释器解释并执行 将结果以产品需要的方式显示出来 二.命令提示符 sq@sq-VirtualBox:~$ ...
- java.util.Stack类简介
Stack是一个后进先出(last in first out,LIFO)的堆栈,在Vector类的基础上扩展5个方法而来 Deque(双端队列)比起Stack具有更好的完整性和一致性,应该被优先使用 ...
- Oracle常用查询命令
Oracle查询完整格式如下: Select * from XX where XX group by YY having XX order by YY Select count(*), XX fr ...
- 20151216JqueryUI---dialog代码备份
$(function () { $('#search_button').button(); /*$('#reg').dialog({ focus:function(e,ui){ alert('注册') ...
- 主机访问 虚拟机web注意事项
在这里, 我通过NAT的方式, 通过主机访问虚拟机. 需要做的是, 将主机中访问的端口, 映射为虚拟机的'编辑->虚拟网络编辑器->vmnet8', 如下图 在弹出的'映射传入端口'界面中 ...
- Java分布式处理技术(RMI,JDNI)
http://hedaoyuan.blog.51cto.com/4639772/813702 1.1 RMI的基本概念 1.1.1 什么是RMI RMI(Remote Method Invocatio ...