【转】__attribute__ 之weak,alias属性

本文深入探讨了C语言中弱符号的定义与应用,包括如何通过属性声明创建弱符号,以及在多个同名函数存在时,弱符号如何被强符号替代的规则。同时,通过具体的GCC编译案例展示了弱符号的实际行为。

//strong.c

#include <stdio.h>

void symbol1()
{
    printf("%s.%s\n",__FILE__,__FUNCTION__);
}
//weak.c

#include <stdio.h>
void symbol1() __attribute__ ((weak,alias("symbol222")));
//void symbol1() __attribute__ ((weak));
void symbol222()
{
    printf("%s.%s\n",__FILE__,__FUNCTION__);
}

int main()
{
    //asm(".weak symbol1\n\t .set symbol1, symbol222\n\t");
    if(symbol1)
 symbol1();
    return 0;
}
////////////////////////////////////////
//gcc weak.c strong.c -o weak
//./weak
//输出:strong.c.symbol1
////////////////////////////////////////
//gcc weak.c -o weak
//./weak
//输出:weak.c.symbol222
////////////////////////////////////////
//总结weak属性
//(1)asm(".weak symbol1\n\t .set symbol1, symbol222\n\t");与
//     void symbol1() __attribute__ ((weak,alias("symbol222")));等效。
//(2)给函数加上weak属性时,即使函数没定义,函数被调用也可以编译成功。
//(3)当有两个函数同名时,则使用强符号(也叫全局符号,即没有加weak的函数)来代替弱符号(加weak的函数)。
//(4)当函数没有定义,但如果是“某个函数”的别名时,如果该函数被调用,就间接调用“某个函数”。

原文见:http://hi.baidu.com/sdwffzlll/item/7c99bef78a30afc7531c26f8

<think> 我们正在讨论C标准库中`_write`函数的属性问题,特别是它是否具有`weak`属性。根据用户提供的引用和问题,我们可以分析如下: 1. 引用[1]提到`weak alias`,并说明如果一个平台没有定义自己的`write(2)`,就会使用一个默认的实现(该实现仅处理错误,不执行实际写操作)。这暗示`write`系统调用可能有弱别名机制。 2. 引用[2]和[3]解释了`weak`和`strong`属性的区别,但主要针对内存管理(如Objective-C的属性)。然而,在C/C++中,`weak`属性在符号链接中也有含义,即允许被覆盖。 在C库实现中,`_write`函数通常被设计为一个弱符号(weak symbol),这样用户可以在自己的程序中覆盖(override)这个函数。例如,在嵌入式系统中,我们经常重写`_write`函数以将输出重定向到串口。 因此,我们可以得出结论:在大多数C库(如glibc、newlib等)中,`_write`函数确实被声明为弱符号(weak symbol)。这意味着: - 如果用户程序没有定义自己的`_write`,则链接时使用C库中的默认实现。 - 如果用户程序定义了`_write`,则使用用户定义的版本。 举例说明(以ARM GCC为例): ```c // 默认的_write(在C库中)可能是这样声明的: __attribute__((weak)) int _write(int fd, char *ptr, int len) { // 默认实现,可能返回错误或调用系统调用 } ``` // 用户可以在自己的代码中覆盖它: int _write(int fd, char *ptr, int len) { // 用户自定义实现,例如通过串口发送数据 for (int i = 0; i < len; i++) { send_char_via_uart(ptr[i]); // 发送字符 } return len; } ``` 在链接时,如果用户提供了自己的`_write`,则弱符号的定义会被忽略,使用用户的定义。 验证方法:我们可以查看C库的源代码。例如,在newlib(常用于嵌入式系统的C库)中,`_write`确实被定义为弱符号。在glibc中,系统调用封装函数通常也是弱符号。 因此,回答用户的问题:**是的,在大多数实现中,`_write`函数具有weak属性**。 为了更严谨,我们还可以考虑标准:C标准本身不规定这些细节,但常见的实现(如glibc, newlib, musl)都采用这种模式以支持用户替换。 --- §§相关问题§§ 1. 如何覆盖C库中的`_write`函数以实现自定义输出? 2. 弱符号(weak symbol)在链接过程中是如何处理的? 3. 在C++中重写`_write`函数需要注意什么? 4. 除了`_write`,还有哪些常用的C库函数可以被覆盖? </think> ### `_write`函数的weak属性分析 根据引用[1]和[3]的说明,我们可以明确回答:**标准库中的`_write`函数通常具有weak属性**。这是C标准库实现中常见的模式,具体分析如下: #### 一、weak属性的基本特性 1. **定义与作用**: - weak属性允许符号在链接时被覆盖(如引用[3]所述)[^3] - 作为"弱引用",当存在同名的强符号时会被忽略 - 实现方式:通过`__attribute__((weak))`或#pragma weak指令 2. **行为表现**: $$ \text{weak符号} \begin{cases} \text{被使用} & \text{当无同名强符号时} \\ \text{被忽略} & \text{当存在同名强符号时} \end{cases} $$ #### 二、_write的weak属性实现 1. **标准库实现**: ```c // glibc示例 (sysdeps/unix/sysv/linux/write.c) ssize_t __write (int fd, const void *buf, size_t nbytes) { // 系统调用实现... } weak_alias (__write, write) // 声明为weak别名[^1] ``` - 使用`weak_alias`宏创建弱符号 - 默认实现仅处理错误和系统调用封装 2. **用户覆盖机制**: ```c // 用户自定义强符号覆盖weak实现 ssize_t write(int fd, const void *buf, size_t count) { log_output(fd, buf, count); // 添加日志功能 return syscall(SYS_write, fd, buf, count); // 调用真实写入 } ``` 当用户定义同名函数时,weak符号会被忽略[^3] 3. **嵌入式系统特例**: ```c // newlib中的声明 (libc/sys/arm/syscalls.c) __attribute__((weak)) int _write(int fd, char *ptr, int len) { // 默认空实现 return -1; } ``` 需要开发者自行实现具体硬件驱动 #### 三、weak属性的设计意义 1. **扩展性需求**: - 允许用户自定义I/O行为(如引用[1]提到的errno处理)[^1] - 支持特殊环境适配(无操作系统的嵌入式场景) 2. **系统兼容机制**: $$ \text{可执行文件} \begin{cases} \text{使用库实现} & \text{当未定义_write时} \\ \text{使用自定义实现} & \text{当已定义_write时} \end{cases} $$ 3. **性能考量**: - 避免不必要的函数调用跳 - 最小化标准库的固有开销 #### 四、验证方法 1. **符号检查**: ```bash nm libc.so | grep ' write' # 输出示例:00000000000a9d70 W write # "W"表示weak符号 ``` 2. **覆盖测试**: ```c #include <unistd.h> #include <stdio.h> // 用户强符号定义 ssize_t write(int fd, const void *buf, size_t count) { printf("Write intercepted!\n"); return 0; } int main() { write(1, "test", 4); // 输出"Write intercepted!" return 0; } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值