strong_alias && weak_alias && __attribute__

來源:互聯網
上載者:User

http://www.cnblogs.com/justinyo/archive/2013/03/12/2956438.html

為了查看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 attribute

This 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
type newname __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"))); // declarationvoid foo(void){
    printf("newname = %d\n", newname); // prints 1}

 

還存在一種weak_alias的概念,對比strong_alias,就是展開的時候多了個__attribute__裡多了個weak

 

alias:表示當前符號是另外一個(目標target)符號的別稱。比如:

?
123 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修飾符僅針對靜態庫產生影響。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.