首页 > 其他分享 >弱符号与强符号 vs 弱引用与强引用

弱符号与强符号 vs 弱引用与强引用

时间:2023-10-29 15:00:54浏览次数:30  
标签:定义 符号 int vs 引用 foo 链接

弱符号与强符号

说明

对于C/C++语言来说,编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号。我们也可以通过GCC的"__attribute__((weak))"来定义任何一个强符号为弱符号。注意,强符号和弱符号都是针对定义来说的,不是针对符号的引用。
比如我们有下面这段程序:

extern int ext;
int weak;
int strong = 1;
_attribute_((weak))weak2=2;

int main()
{
    return 0;
}

上面这段程序中,"weak"和"weak2"是弱符号,"strong"和"main"是强符号,而"ext"既非强符号也非弱符号,因为它是一个外部变量的引用。针对强弱符号的概念,链接器就会按如下规则处理与选择被多次定义的全局符号:

  • 规则1:不允许强符号被多次定义(即不同的目标文件中不能有|同名的强符号):如果
    有多个强符号定义,则链接器报符号重复定义错误。

  • 规则2:如果一个符号在某个目标文件中是强符号,在其他文件中中都是弱符号,那么选
    择强符号。

  • 规则3:如果一个符号在所有目标文件中都是弱符号,那么选择其中占用空间最大的一
    个。比如目标文件A定义全局变量global为int型,占4个字节;目标文件B定义global
    为double型,占8个字节,那么目标文件A和B链接后,符号global占8个字节(尽)
    量不要使用多个不同类型的弱符号,否则容易导致很难发现的程序错误)。

使用场景

比如系统可以预定义一个弱符号的函数,或者弱符号的变量。如果用户想自己修改。那么用户的只需要定义对应的强符号,就会覆盖系统的默认行为。

弱引用与强引用

说明

目前我们所看到的对外部目标文件的符号引用在目标文件被最终链接成可执行文件时,它们须要被正确决议,如果没有找到该符号的定义,链接器就会报符号未定义错误,这种被称为强引用(StrongReference)。与之相对应还有一种弱引用(WeakReference),在处理弱引用时,如果该符号有定义,则链接器将使用该符号的引用决议:如果该符号未被定义,则链接器对于该引用不报错
链接器处理强引用和弱引用的过程几乎一样,只是对于未定义的弱引用,链接器不认为它是一个错误。一般对于未定义的弱引用,链接器默认其为0,或者是一个特殊的值,以便于程序代码能够识别。弱引用和弱符号主要用于库的链接过程,我们将在"库"这一章再来详细讲述。

__attribute__((weakref)) void foo();
int main()
{
   if (foo)
       foo();
}

我们可以将它编译成一个可执行文件,GCC并不会报链接错误。但是当我们运行这个可执行文件时,会发生运行错误。因为当main函数试图调foo函数时,foo函数的地址为
0,于是发生了非法地址访问的错误。

使用场景

这种弱符号和弱引用对于库来说十分有用,比如库中定义的,弱符号可以被用户定义的强符号所覆盖,从而使得程序可以使用自定义版本的库函数;或者程序可以对某些扩展功能模块的引用定义为弱引用,当我们将扩展模块与程序链接在一起时,功能模块就可以正常使用;如果我们去掉了某些功能模块,那么程序也可以正常链接,只是缺少了相应的功能,这使得程序的功能更加容易裁剪和组合。

标签:定义,符号,int,vs,引用,foo,链接
From: https://www.cnblogs.com/lvzh/p/17794783.html

相关文章

  • Offset多维引用
    问题:为何使用Vlookup套Offset查找三个表中对应结果会出错公式:=VLOOKUP(C12,OFFSET(C4,,{0,3,6},3,2),2,)Offset,以C4为起点,向右分别偏移0、3、6,产生新单元格区域为3行两列,这一结果为多维引用,无法在同一单元格内正常显示Vlookup函数无法提取多维引用的结果多维引用解法1:=SUM......
  • win10 openocd通过vscode远程调试stm32的uboot--Apple的学习笔记
    一,前言我在uboot支持的cortex-M4内核启动流程分析--Apple的学习笔记中就说过了,我计划要单步调试uboot,但是我只有stlink,所以要基于openocd的gdb来调试,所以就做了尝试,花费约2天时间,虽然做了些无用功,专门还装了ubuntu18.04,且基于ubuntu还安装了openocd这些其实都无用的,但是就是这些过......
  • Token vs 单词
    要让LLMs(LargeLanguageModels,大型语言模型)生成文字,首先得让它们“懂”单词。单词首先会被拆分为Tokens(一种能够被编码的基础单元)。在不同的语言模型和分词系统中,Token的定义和分割方法可能会有所不同。绝大多数情况下,一个单词对应一个Token,但是也有很多情况不能一一对应。......
  • Ethernet vs. EtherCAT
    Ethernet也就是以太网,算是一种链路层的协议(IEEE802.3)。如下图所示,链路层datalinklayer位于网络层和物理层中间。因此链路层的基本服务是将数据报通过单一通信链路从一个节点移动到相邻节点,但所提供的服务细节取决于链路层协议。链路层协议能够提供的可能服务包括:1.成帧frami......
  • vscode 安装了clang之后 即使卸载也没有跳转功能记录
     借鉴这位博主  【精选】VSCodeC/C++无法跳转到定义、自动补全、悬停提示功能_c/c++:editconfigurations(json)-CSDN博客 (上图高亮部分)卸载clang 重启VSCode 然后IntelliSenseEngine开关设置为Default 应该就可以了 ......
  • VS and C++ Versions
    VS版本VC版本ToolSet版本MSC版本VisualStudio66 1200VisualStudio20037 1300VisualStudio20058801400VisualStudio20089901500VisualStudio2010101001600VisualStudio2012111101700VisualStudio2013121201800......
  • thymeleaf引用JS加随机数防止缓存
    一、运行环境1、Thymeleaf2.2.22、SpringBoot2.6.4二、实际代码<scriptth:src="@{/back/js/cloud/manageAddress.js(__${#httpServletRequest.getSession().getId()}__)}"></script>说点废话。都说ChatGPT智能,至少我感觉3.5一般国内有人搭建了要收费 其实ChatGPT对写代码还是......
  • vscode 创建代码片段
    1vscode左下角设置>命令面板2输入snippets3选择新建全局代码片段文件4输入文件名称xxx.json(例如:vue-setup-less.json)5设置模板并保存快捷生成模板地址点击跳转......
  • MicroSIP-3.21.3+pjproject-2.13.1+ opus-1.3.1+VS2019
    本文记录了我通过VS2019编译MicroSIP-3.21.3开源项目的过程。Microsip:MicroSIPsourcecodepjproject:DownloadPJSIP-OpenSourceSIP,Media,andNATTraversallibraryopus:Downloads–OpusCodec(opus-codec.org)下载并解压后如图: 用vs2019将microsip的平......
  • C++引用
    C++引用引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字,一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。C++引用vs指针引用很容易与指针混淆,它们之间有三个主要区别:不存在空引用,引用必须连接到一块合法的内存一旦引用被初始化为一个对象......