為了查看linux下malloc的實現函數,下載了Glibc的源碼文件,可是找不到實現的函數在哪里。
看文件名 應該是在malloc/malloc.c里面。
發現__libc_malloc的實現比較像。
怎么從malloc到__libc_malloc的呢?
看到文件里有一個語句
有點苗頭
來看看strong_alias的實現
_typeof (name) aliasname 就是定義別名的意思了 至於后面的__attribute__看下面的解釋。
GNU C的一大特色(卻不被初學者所知)就是__attribute__機制。
__attribute__可以設置函數屬性(Function Attribute)、變量屬性(Variable Attribute)和類型屬性(Type Attribute)
__attribute__前后都有兩個下划線,並且后面會緊跟一對原括弧,括弧里面是相應的__attribute__參數
__attribute__語法格式為:
__attribute__ ( ( attribute-list ) )
函數屬性(Function Attribute),函數屬性可以幫助開發者把一些特性添加到函數聲明中,從而可以使編譯器在錯誤檢查方面的功能更強大。
__attribute__機制也很容易同非GNU應用程序做到兼容。
GNU CC需要使用 –Wall,這是控制警告信息的一個很好的方式。
就這樣定義了malloc的是__libc_malloc的別名,__malloc也是__libc_malloc的別名。
__attribute__((alias))
variable attributeThis variable attribute enables you to specify multiple aliases for variables.
Where a variable is defined in the current translation unit, the alias reference is replaced by a reference to the variable, and the alias is emitted alongside the original name. Where a variable is not defined in the current translation unit, the alias reference is replaced by a reference to the real variable. Where a variable is defined as static, the variable name is replaced by the alias name and the variable is declared external if the alias is declared external.
Note
Function names might also be aliased using the corresponding function attribute
__attribute__((alias))
.
Syntax
typenewname
__attribute__((alias("oldname
")));Where:
oldname
is the name of the variable to be aliased
newname
is the new name of the aliased variable.
Example
#include <stdio.h> int oldname = 1; extern int newname __attribute__((alias("oldname"))); // declaration void foo(void) {printf("newname = %d\n", newname); // prints 1 }
還存在一種weak_alias的概念,對比strong_alias,就是展開的時候多了個__attribute__里多了個weak
alias:表示當前符號是另外一個(目標target)符號的別稱。比如:
void __f () { /* Do something. */; } void f () __attribute__ ((weak, alias ("__f")));
alias修飾的是符號f,指定的目標符號是__f,也就是說符號f是符號__f的別稱。
weak:表示當前符號是個弱類型符號(weak symbol),而非全局符號。看個示例:
1,首先,准備一個庫文件(以靜態庫為例,后文將提到為什么不以動態庫為例):
[root@localhost weak_test1]# cat /etc/issue
CentOS release 6.2 (Final)
Kernel \r on an \m
[root@localhost weak_test1]# uname -a
Linux localhost.localdomain 2.6.32-220.el6.i686 #1 SMP Tue Dec 6 16:15:40 GMT 2011 i686 i686 i386 GNU/Linux
[root@localhost weak_test1]# vi mylib.c
[root@localhost weak_test1]# cat !$
cat mylib.c
#include <stdio.h>
void
foo()
{
printf
(
"lib test\n"
);
}
void
foo() __attribute__ ((weak));
[root@localhost weak_test1]# <span
class
=
"wp_keywordlink_affiliate"
><a href=
"http://lenky.info/tag/gcc/"
title=
"查看 gcc 中的全部文章"
>gcc</a></span> -c mylib.c
[root@localhost weak_test1]# ar crv libmylib.a mylib.o
a - mylib.o
可以看到libmylib.a庫里定義了一個函數foo(),並且是weak弱類型。
2,編寫一個應用程序(由兩個源文件myapp.c與myfoo.c構成):
[root@localhost weak_test1]# vi myapp.c
[root@localhost weak_test1]# cat !$
cat myapp.c
#include <stdio.h>
int
main()
{
foo();
return
0;
}
[root@localhost weak_test1]# vi myfoo.c
[root@localhost weak_test1]# cat !$
cat myfoo.c
#include <stdio.h>
void
foo()
{
printf
(
"app test\n"
);
}
源文件myfoo.c調用的foo()函數可以來自libmylib.a庫,也可以來自應用程序的另外一個源文件,連接並執行:
[root@localhost weak_test1]# gcc myapp.c myfoo.c libmylib.a -o myapp_weak
[root@localhost weak_test1]# ./myapp_weak
app test
打印顯示的是app test,即調用的是應用程序自身的函數foo()。
3,如果應用程序本身不提供函數foo(),那么情況是怎樣:
[root@localhost weak_test1]# gcc myapp.c libmylib.a -o myapp
[root@localhost weak_test1]# ./myapp
lib test
打印顯示的是lib test,即調用了libmylib.a庫里的weak弱類型函數foo()。
4,試試去掉庫里的weak修飾:
[root@localhost weak_test1]# vi mylib.c
[root@localhost weak_test1]# cat mylib.c
#include <stdio.h>
void
foo()
{
printf
(
"lib test\n"
);
}
//void foo() __attribute__ ((weak));
[root@localhost weak_test1]# gcc -c mylib.c;ar crv libmylib.a mylib.o
r - mylib.o
[root@localhost weak_test1]# gcc myapp.c myfoo.c libmylib.a -o myapp
[root@localhost weak_test1]# ./myapp
app test
去掉weak修飾后也沒問題?那weak屬性到底有啥用?試試把libmylib.a放前面:
[root@localhost weak_test1]# gcc myapp.c libmylib.a myfoo.c -o myapp
/tmp/ccIjvazY.o: In function `foo':
myfoo.c:(.text+0x0): multiple definition of `foo'
libmylib.a(mylib.o):mylib.c:(.text+0x0): first defined here
collect2: ld returned 1
exit
status
[root@localhost weak_test1]# gcc libmylib.a myapp.c myfoo.c -o myapp
[root@localhost weak_test1]# gcc libmylib.a myfoo.c myapp.c -o myapp
[root@localhost weak_test1]# gcc myfoo.c libmylib.a myapp.c -o myapp
[root@localhost weak_test1]# gcc myfoo.c myapp.c libmylib.a -o myapp
對比一下,加上weak修飾:
[root@localhost weak_test1]# vi mylib.c
[root@localhost weak_test1]# cat mylib.c
#include <stdio.h>
void
foo()
{
printf
(
"lib test\n"
);
}
void
foo() __attribute__ ((weak));
[root@localhost weak_test1]# gcc -c mylib.c;ar crv libmylib.a mylib.o
r - mylib.o
[root@localhost weak_test1]# gcc myapp.c libmylib.a myfoo.c -o myapp
[root@localhost weak_test1]# gcc libmylib.a myapp.c myfoo.c -o myapp
[root@localhost weak_test1]# gcc libmylib.a myfoo.c myapp.c -o myapp
[root@localhost weak_test1]# gcc myfoo.c libmylib.a myapp.c -o myapp
[root@localhost weak_test1]# gcc myfoo.c myapp.c libmylib.a -o myapp
[root@localhost weak_test1]# ./myapp
app test
去掉weak修飾后,只有一個杯具的報錯了,難道是和庫文件排放位置相關?不用庫函數,直接用源代碼試試:
[root@localhost weak_test1]# vi mylib.c
[root@localhost weak_test1]# cat mylib.c
#include <stdio.h>
void
foo()
{
printf
(
"lib test\n"
);
}
//void foo() __attribute__ ((weak));
[root@localhost weak_test1]# gcc myapp.c myfoo.c mylib.c -o myapp
/tmp/ccbKVCYU.o: In function `foo':
mylib.c:(.text+0x0): multiple definition of `foo'
/tmp/cc3DKEyS.o:myfoo.c:(.text+0x0): first defined here
collect2: ld returned 1
exit
status
[root@localhost weak_test1]# gcc myapp.c mylib.c myfoo.c -o myapp
/tmp/ccosX9JJ.o: In function `foo':
myfoo.c:(.text+0x0): multiple definition of `foo'
/tmp/ccyyg6us.o:mylib.c:(.text+0x0): first defined here
collect2: ld returned 1
exit
status
報錯(必然的),加上:
[root@localhost weak_test1]# vi mylib.c
[root@localhost weak_test1]# cat mylib.c
#include <stdio.h>
void
foo()
{
printf
(
"lib test\n"
);
}
void
foo() __attribute__ ((weak));
[root@localhost weak_test1]# gcc myapp.c myfoo.c mylib.c -o myapp
[root@localhost weak_test1]# gcc myapp.c mylib.c myfoo.c -o myapp
啥結論?看來weak修飾符的原本含義是讓weak弱類型的函數可以被其它同名函數覆蓋(即不會發生沖突),如果沒有其它同名函數,就使用該weak函數,類似於是默認函數;
但是,受到“庫”這一特別存在的影響,weak弱類型對庫變得“不太可靠”了,而且根據Weak definitions aren’t so weak來看,對於新版本的glibc,weak修飾符僅針對靜態庫產生影響。