GNU C - Using GNU GCC __attribute__ mechanism 01 Function Attribute


近來閱讀glibc源碼的時候遇到很多關於__attribute__的問題,索性就查找了相關的資料,學習了一下.

要是不解決了這個問題,有的時候還真的是比較難下手.就拿glibc來說,使用xcscope搜索POSIX pthread

函數: pthread_create,得到的結果如下:

如果一路跟進函數的話,最后會發現這樣子的一個宏定義:

 

下面是GNU glibc開發人員對此類宏的注釋,看起來直白一點:

 

 現在只是知道,在鏈接的時候,尋找pthread_create會被鏈接到__pthread_create_2.1/__pthread_create_2.0.


上面展現的是GNU glibc中很常用的編程技巧,這不是本文的重點,關於這點,我也沒有深究.如果,有了解的同學可以給我留信息哈.希望多多指教.

 

下面來說說另外一種,glibc中很多地方都使用別名機制,都合 gnu gcc的 __attribute__ mechanism有關系.在gcc的文檔中有關於 Attribute syntax 的章節,

其中就講解了_attribute__ mechanism. 參考鏈接如下:

             Attribute Syntax: http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Attribute-Syntax.html#Attribute-Syntax

 

Attribute Syntax分為三個部分:

    Function Attribute:  函數attribute語義

              Variable  Attribute:   變量attribute語義

      Type       Attribute:   類型attribute語義

 

 

下面就各選取第一部分中一些內容,解釋一下:

一、Function Attribute:

1.__attribute__((alias)):  為一個symbol聲明一個別名

 

return-type newname([arguments-list]) __attribute__((alias("oldname")))

 

 oldname:  原始函數名

 newname:   原始函數的別名

 來看看glibc中 _strong_alias宏的實現:

 

 最后一句中 __typeof(name) 就是原始函數的返回類型, aliasname是別名, 后面的就不需要解釋了吧...

 下面看一段小程序吧:

 

#include <stdio.h>
#include <stdlib.h>

void foo()
{
	printf("\nInside %s\n",__FUNCTION__);
}

void _foo() __attribute__((alias("foo")));

//@Author : forest
int main(int args,char ** argv)
{
	_foo();
	return EXIT_SUCCESS;
}

 

 輸出很簡單,就是通過別名調用了原始函數.

 

2.__attribute__((const)): const這個attribute是在gcc2.5以后添加的,以前的舊版本是沒有的.const attribute只能用於帶有數值參數類型的函數上.

           因為帶有數值參數的函數返回值是相同的,所以在多次調用的時候,編譯器進行優化,只需要執行一次就可以得到執行的結果.

              const attribute是讓編譯器進行優化.

int Function_Attribute_const_0(int b) __attribute__((const));
int Function_Attribute_const_0(int b)
{
      int aLocal = 0;
      aLocal += Function_Attribute_const_0(b);
      aLocal += Function_Attribute_const_0(b);
      return aLocal;
}

 其中的"Function_Attribute_const_0(int)"函數將會執行一次.

 


3.__attribute__((constructor|destructor(PRIORITY))): 這個在上篇博文中已經說過了:
GNU C - 一個別致的HelloWorld程序 引申到: __attribute__((constructor)|(destructor)(PRIORITY))

 

4.__attribute__((deprecated)): deprecated,棄用. 如果在源文件在任何地方地方使用deprecated attribute函數,編譯器將會發出警告.

   __attribute__((deprecated(MSG))): MSG,將在編譯器warnning中輸出.

下面改寫一下前面的小例子:

 

#include <stdio.h>
#include <stdlib.h>

__attribute__((deprecated("foo函數已經被棄用"))) void foo() 
{
	printf("\nInside %s\n",__FUNCTION__);
}

void _foo() __attribute__((alias("foo")));

//@Author : forest
int main(int args,char ** argv)
{
	_foo();

	foo();
	return EXIT_SUCCESS;
}

 

 Output:

可以看出在上面的例子中,聲明foo()被棄用,在main()中被調用在編譯的時候會拋出warnning.但是使用別名調用就不會輸出

warnning.官網的資料中關於這點沒有相關介紹,以實踐為准吧.

 

5.__attribute__(format(archetype,string-index,first-to-check)): format attribute提供了對printf, scanf, strftime, strfmon類型函數

的參數和對應format類型的檢查.(這英文翻譯起來有點別扭,將就一下吧~)

glibc中有很多關於format attribute的使用:

 

 archtype: 決定format string將會被怎樣解釋.解釋的類型應該是printf, scanf, strftime, gnu_printf, gnu_scanf, gnu_strftime..(也可以像glibc一樣使用__printf__,

__scanf__,__strftime ...以下划線開始和結尾).


string-index: 函數的參數從左到右以此序號為1,2,3遞增.string-index就是fmt的序號.

 

first-to-check: 參數列表中第一個和fmt形式比較的參數.

 

#include <stdio.h>
#include <stdlib.h>

void foo(const char *fmt,...) \
	__attribute__((__format__(__printf__,1,2)));

//@Author : forest
int main(int args,char ** argv)
{
	//@test
	foo("\n%d %d","test_a","test_b");	

	return EXIT_SUCCESS;
}

void foo(const char *fmt,...)
{
	/*do nothing*/
}

 

輸出結果如下:

 

 

 

6.__attribute__((weak)): weak symbol,弱符號. 若存在兩個相同的全局符號時,會引發重定義錯誤. 如果使用weak attribute,則當

                                       weak symbol和non-weak symbol同時存在的時候,linker會使用non-weak symbol.若只有weak symbol

              存在的時候則只使用weak symbol.

glibc中有大量的實例:

 

 

補充: __attribute__ 后面的屬性字段也是可以連在一起用的。

 

 到這里,第一部分就算完了。如果粗略看了一下這些,閱讀一些源碼庫基本上就不會出現找不到函數實現的問題了.

 掃平一切障礙~

 

 

        

      

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM