__attribute__((weak))关键字如何使用?

嵌入式大杂烩 2022-05-20 21:30

来源:CSDN

作者 | ZC.Shou

整理 | 嵌入式应用研究院

今天在使用 Keil (主要是 armcc 编译器)编译代码(华大的 MCU 驱动库hc32f46x_interrupts.h / c)的时候遇到了有 __weak 关键字的函数不起作用的问题,甚是奇怪。之前对于 __weak 关键字一直是一个简单的认知:编译器自动使用没有 __weak 的同名函数(如果有的话)替换有 __weak 关键字的同名函数,__weak 函数可以没有定义,且编译器不会报错!至于这个参数详细的使用细节一直是一知半解,今天借此机会,以 GCC 作为对比,来学习一下 ARM 中的 __weak 关键字的具体使用!

来源

使用过 GCC 以及有 linux 编程经验的人,对于这个关键字应该不陌生。GNU 的编译器(gcc)扩展了一个关键字 attribute,通过该关键字,用户可以在声明时指定特殊的属性,使用时该关键字后跟双括号内的属性,例如:attribute((属性名字))。属性名字都是定义好的,Weak 属性就是其中之一:attribute((weak))。在 linux 源码中,该关键字非常常见:

GCC 不多介绍,重点关注 ARM。在 ARM 编译器(armcc)中,支持和 GCC 相同的关键字 attribute,使用方式也基本相同,如下:

__attribute__((attribute1, attribute2, ...))   // 例如:void * Function_Attributes_malloc_0(int b) __attribute__((malloc));
__attribute__((__attribute1__, __attribute2__, ...))    // 例如:static int b __attribute__((__unused__));

当函数属性发生冲突时,编译器将使用更安全或更强的一个

除此之外,ARM 编译器(armcc)还扩展了一个关键字 __weak,例如:__weak void f(void); 或者 __weak int i;。ARM 的汇编器(armasm)以另一种方式 [WEAK]支持该特性。

注意:

在许多源码中,经常通过宏定义的形式来定义关键字,例如 上面linux 中的__weak就是 宏定义的 __attribute__((weak))

强/弱符号

在 GCC 中,被__attribute__((weak))修饰的符号,我们称之为 弱符号(Weak Symbol)。例如:弱函数、弱变量;没有__attribute__((weak))修饰的符号被称为强符号。在 ARM 中,没有弱符号和强符号这种叫法,只有个弱引用(Weak References)和 非弱引用(non-weak reference ) 、 弱定义(Weak definitions)和 非弱定义(non-weak definition)的介绍章节。 非弱引用就是我们平常使用的对于非弱函数或者弱变量的引用。如果链接器无法在到目前为止已加载内容中解析对正常非弱符号的引用问题,则 它会尝试通过在库中找到符号 来解决此问题:

  • 如果找不到此类引用,则链接器将报告错误。
  • 如果解析了这样的引用,则从入口点可以通过至少一个非弱引用来访问的节区被标记为已使用。这样可以确保链接器不会将该节作为未使用的节删除。每个非弱引用都必须通过一个定义来解决。如果有多个定义,则链接器将报告错误。

弱引用

引用弱声明的函数或者变量的引用即为弱引用。链接器不会从库中加载对象来解析弱引用。仅当由于其他原因在镜像中包含了定义时,它才能解析弱引用。弱引用不会导致链接器将包含定义的节区标记为已使用,因此链接器可能会将其标记为未使用而删除。

__weak

__weak 关键字可以应用于函数和变量的声明以及函数定义。

声明

__weak 可以用于函数声明或者变量的声明。对于声明,此存储类指定一个 extern 对象声明,即使该对象不存在,对于该声明的引用也不会导致链接器对未解析的引用(找不到定义的引用)当做错误来处理。

如果在当前编译单元中可以找到 __weak 声明定义,则会用找到的定义替换 __weak 引用;对于找不到定义 __weak 的声明(函数或变量,如上图的 FuncB),编译器做如下处理:

  • 引用被解析为分支连接指令 BL。等效于将被引用的分支为 NOP
  • 直接将引用替换为 NOP 指令 注意:必须是在当前编译单元,不再当前编译单元的没有意义(例如 ExtFuncA 在 main.c 中只有__weak 声明,但是没有定义)。具体看下图的测试代码:

注意:用 __weak 声明然后不使用 _weak 定义的函数的行为相当于非弱函数。这与 attribute((weak)) 关键字不同!

定义

用 __weak 定义的函数弱输出其符号。弱定义的函数的行为类似于正常定义的函数,除非将同名的非弱定义的函数链接到同一镜像中。如果在同一镜像中同时存在非弱定义函数和弱定义函数,则对该函数的所有调用都会解析为调用非弱函数,否则直接使用弱定义的函数(与上面的若声明不同)。

如果可以使用多个弱定义,则除非使用链接器选项 --muldefweak,否则链接器会生成一条错误消息。在这种情况下,链接器随机选择一个供所有调用来使用。使用方式如下:

/* a.h !!!注意所在文件不同!!! */
void FuncA(void);
void FuncB(void);

/* a.c !!!注意所在文件不同!!! */
void FuncA(void)
{
    FuncB();        /* 这里将替换为 main.c 中的 FuncB */
}

__weak void FuncB(void)     /* 弱定义 */
{

}

/* main.c !!!注意所在文件不同!!! */
void FuncB(void)
{

}

int main (void)
{
 FuncB();
}

注意,函数的声明一定不能添加 __weak 关键字。具体如下图:

限制

  • 1数或变量不能在同一编译中同时弱和非弱地使用
void f(void);

void g()
{
    f();    /* 非弱函数引用 */
}

__weak void f(void);

void h()
{
    f();    /* 弱函数引用 */
}
  • 2.不能在定义函数或变量的同一编译中使用弱函数或弱变量,如下将导致编译错误(正确的使用方式参考上面的使用示例):
/* a.c 如下同一文件中的定义及使用将报错 */
__weak void f(void);

void h()
{
    f();
}

void f()
{

}

弱函数不能是内联函数

attribute((weak))

__attribute__关键字使您可以指定变量或结构字段,函数和类型的特殊属性(与具体属性)。该关键字的作用与 __weak 的作用基本是一样的,在使用时有些不同,此外在某些情况下,编译的处理也有些区别。

声明

这个参数是 GUN 编译器的一个扩展,ARM 编译器也支持该关键字。__attribute__((weak))可以声明弱变量,并且其声明方式与 __weak相比更加灵活。除了__weak 的声明方式,我们还可以用 extern int Variable_Attributes_weak_1 __attribute__((weak));

_attribute__((weak))可以声明弱函数,其声明方式与__weak相比更加灵活。除了 __weak的声明方式,我们还可以用 extern int Function_Attributes_weak_0 (int b) __attribute__((weak));。

任何包含了__attribute__((weak)); 声明的文件的中的同名函数定义,都将被当做弱函数。如下图:

开篇提出的问题就是因为上图所示的这种情况!

注意:用 __attribute__((weak))声明然后不使用__attribute__((weak))进行定义的函数的行为就像是弱函数。这与__weak关键字的用法不同。

在 GNU 模式中需要 extern 限定符。在非 gnu 模式下,编译器假设如果变量不是 extern,那么它将像对待其他非弱变量一样对待。

定义

用 __attribute__((weak))定义的函数弱输出其符号(与__weak相同)。其使用方式有以下两种:

__attribute__((weak)) void FuncA(void)
{
    printf("Weak FuncA!\r\n");
}
/* 或者 */
void __attribute__((weak)) FuncA(void)
{
    printf("Weak FuncA!\r\n");
}

注意:用__attribute__((weak))声明然后不使用__attribute__((weak))进行定义的函数的行为就像是弱函数。这与__weak关键字的用法不同。除此之外,没有啥不同,这里不再多说!

区别

  • 1.如上介绍,__weak__attribute__((weak))在声明和定义的时候,其所处的位置有不同。
  • 2.__weak仅在函数定义中使用时才会生成弱函数。而在任何情况下(声明和定义)__attribute__((weak))都会生成弱函数,无论是用于函数定义还是用于函数声明中!

参考

https://community.arm.com/developer/tools-software/tools/f/keil-forum/34584/run-error-when-use-__weak-to-define-function https://blog.csdn.net/rensheng__rumeng/article/details/78634804 http://blog.sina.com.cn/s/blog_62d3426b0100g7n6.html http://www.keil.com/support/man/docs/armcc/armcc_chr1359124970859.htm http://infocenter.arm.com/help/topic/com.arm.doc.dui0472j/DUI0472J_armcc_user_guide.pdf https://github.com/ARM-software/CMSIS_5/issues/141


版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。


猜你喜欢:

一个很棒的智能配网方案!

分享一款小巧好用的代码对比工具

一个300多行代码实现的多任务管理的OS

分享嵌入式中几个实用的shell脚本!

分享一份嵌入式软件工具清单!

在公众号聊天界面回复1024,可获取嵌入式资源;回复 ,可查看文章汇总。

嵌入式大杂烩 专注于嵌入式技术,包括但不限于C/C++、嵌入式、物联网、Linux等编程学习笔记,同时,内包含大量的学习资源。欢迎关注,一同交流学习,共同进步!
评论
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-12 10:13 31浏览
  • RK3506 是瑞芯微推出的MPU产品,芯片制程为22nm,定位于轻量级、低成本解决方案。该MPU具有低功耗、外设接口丰富、实时性高的特点,适合用多种工商业场景。本文将基于RK3506的设计特点,为大家分析其应用场景。RK3506核心板主要分为三个型号,各型号间的区别如下图:​图 1  RK3506核心板处理器型号场景1:显示HMIRK3506核心板显示接口支持RGB、MIPI、QSPI输出,且支持2D图形加速,轻松运行QT、LVGL等GUI,最快3S内开
    万象奥科 2024-12-11 15:42 86浏览
  • 时源芯微——RE超标整机定位与解决详细流程一、 初步测量与问题确认使用专业的电磁辐射测量设备,对整机的辐射发射进行精确测量。确认是否存在RE超标问题,并记录超标频段和幅度。二、电缆检查与处理若存在信号电缆:步骤一:拔掉所有信号电缆,仅保留电源线,再次测量整机的辐射发射。若测量合格:判定问题出在信号电缆上,可能是电缆的共模电流导致。逐一连接信号电缆,每次连接后测量,定位具体哪根电缆或接口导致超标。对问题电缆进行处理,如加共模扼流圈、滤波器,或优化电缆布局和屏蔽。重新连接所有电缆,再次测量
    时源芯微 2024-12-11 17:11 109浏览
  • 本文介绍瑞芯微RK3588主板/开发板Android12系统下,APK签名文件生成方法。触觉智能EVB3588开发板演示,搭载了瑞芯微RK3588芯片,该开发板是核心板加底板设计,音视频接口、通信接口等各类接口一应俱全,可帮助企业提高产品开发效率,缩短上市时间,降低成本和设计风险。工具准备下载Keytool-ImportKeyPair工具在源码:build/target/product/security/系统初始签名文件目录中,将以下三个文件拷贝出来:platform.pem;platform.
    Industio_触觉智能 2024-12-12 10:27 43浏览
  • 天问Block和Mixly是两个不同的编程工具,分别在单片机开发和教育编程领域有各自的应用。以下是对它们的详细比较: 基本定义 天问Block:天问Block是一个基于区块链技术的数字身份验证和数据交换平台。它的目标是为用户提供一个安全、去中心化、可信任的数字身份验证和数据交换解决方案。 Mixly:Mixly是一款由北京师范大学教育学部创客教育实验室开发的图形化编程软件,旨在为初学者提供一个易于学习和使用的Arduino编程环境。 主要功能 天问Block:支持STC全系列8位单片机,32位
    丙丁先生 2024-12-11 13:15 63浏览
  • 一、SAE J1939协议概述SAE J1939协议是由美国汽车工程师协会(SAE,Society of Automotive Engineers)定义的一种用于重型车辆和工业设备中的通信协议,主要应用于车辆和设备之间的实时数据交换。J1939基于CAN(Controller Area Network)总线技术,使用29bit的扩展标识符和扩展数据帧,CAN通信速率为250Kbps,用于车载电子控制单元(ECU)之间的通信和控制。小北同学在之前也对J1939协议做过扫盲科普【科普系列】SAE J
    北汇信息 2024-12-11 15:45 110浏览
  • 在智能化技术快速发展当下,图像数据的采集与处理逐渐成为自动驾驶、工业等领域的一项关键技术。高质量的图像数据采集与算法集成测试都是确保系统性能和可靠性的关键。随着技术的不断进步,对于图像数据的采集、处理和分析的需求日益增长,这不仅要求我们拥有高性能的相机硬件,还要求我们能够高效地集成和测试各种算法。我们探索了一种多源相机数据采集与算法集成测试方案,能够满足不同应用场景下对图像采集和算法测试的多样化需求,确保数据的准确性和算法的有效性。一、相机组成相机一般由镜头(Lens),图像传感器(Image
    康谋 2024-12-12 09:45 74浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-11 17:58 83浏览
  • 全球智能电视时代来临这年头若是消费者想随意地从各个通路中选购电视时,不难发现目前市场上的产品都已是具有智能联网功能的智能电视了,可以宣告智能电视的普及时代已到临!Google从2021年开始大力推广Google TV(即原Android TV的升级版),其他各大品牌商也都跟进推出搭载Google TV操作系统的机种,除了Google TV外,LG、Samsung、Panasonic等大厂牌也开发出自家的智能电视平台,可以看出各家业者都一致地看好这块大饼。智能电视的Wi-Fi连线怎么消失了?智能电
    百佳泰测试实验室 2024-12-12 17:33 46浏览
  • 铁氧体芯片是一种基于铁氧体磁性材料制成的芯片,在通信、传感器、储能等领域有着广泛的应用。铁氧体磁性材料能够通过外加磁场调控其导电性质和反射性质,因此在信号处理和传感器技术方面有着独特的优势。以下是对半导体划片机在铁氧体划切领域应用的详细阐述: 一、半导体划片机的工作原理与特点半导体划片机是一种使用刀片或通过激光等方式高精度切割被加工物的装置,是半导体后道封测中晶圆切割和WLP切割环节的关键设备。它结合了水气电、空气静压高速主轴、精密机械传动、传感器及自动化控制等先进技术,具有高精度、高
    博捷芯划片机 2024-12-12 09:16 82浏览
  • 应用环境与极具挑战性的测试需求在服务器制造领域里,系统整合测试(System Integration Test;SIT)是确保产品质量和性能的关键步骤。随着服务器系统的复杂性不断提升,包括:多种硬件组件、操作系统、虚拟化平台以及各种应用程序和服务的整合,服务器制造商面临着更有挑战性的测试需求。这些挑战主要体现在以下五个方面:1. 硬件和软件的高度整合:现代服务器通常包括多个处理器、内存模块、储存设备和网络接口。这些硬件组件必须与操作系统及应用软件无缝整合。SIT测试可以帮助制造商确保这些不同组件
    百佳泰测试实验室 2024-12-12 17:45 39浏览
  • 首先在gitee上打个广告:ad5d2f3b647444a88b6f7f9555fd681f.mp4 · 丙丁先生/香河英茂工作室中国 - Gitee.com丙丁先生 (mr-bingding) - Gitee.com2024年对我来说是充满挑战和机遇的一年。在这一年里,我不仅进行了多个开发板的测评,还尝试了多种不同的项目和技术。今天,我想分享一下这一年的故事,希望能给大家带来一些启发和乐趣。 年初的时候,我开始对各种开发板进行测评。从STM32WBA55CG到瑞萨、平头哥和平海的开发板,我都
    丙丁先生 2024-12-11 20:14 68浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦