GCC __atrribute__

阅读数:518 评论数:0

跳转到新版页面

分类

C/C++

正文

一、概述

1、作用

__attribute__ 可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。

2、位置

其位置约束为:  放于声明的尾部“;” 之前

3、语法格式

__attribute__ 书写特征为:  __attribute__ 前后都有两个下划线,并切后面会紧跟两对括弧,括弧里面是相应的__attribute__ 参数,多个参数以逗号分隔,或者是连接使用多个__attribute__。

__attribute__ 语法格式为:  __attribute__ ((attribute-list))

二、设置函数属性

1、通用的设置

alias("target")

为已存在函数定义别名,例如

void __f () { /* Do something. */; }
void f () __attribute__ ((weak, alias ("__f")));

定义“f”为“__f”的弱别名。

aligned(alignment) 定义了函数在内存中对齐的最小字节数。它会覆盖-falign-functions配置项,另外在许多系统上,链接器可能会影响这个值的最大配置。
alloc_align

用于告诉编译器函数返回值指向内存,且内存的对齐方式由alloc_align中的参数指定。例如

void* my_memalign(size_t, size_t) __attribute__((alloc_align(1)))

alloc_size

用于告诉编译器函数返回值指向的内存,其大小是由alloc_size中的参数指定。主要用于提高__builtin_object_size的正确性。例如

void* my_calloc(size_t, size_t) __attribute__((alloc_size(1,2)))
void* my_realloc(void*, size_t) __attribute__((alloc_size(2)))

always_inline 强制函数做inline处理。
artificial 取决于调试信息格式,可能把一个函数标记为artifical或者在一个inline块内标志调用位置
assume_aligned

用于告诉编译器函数返回值指向的内存对齐方式,一个参数表示最小对齐单位,两个参数中第二个参数表示在对齐单位基础上的偏移量。例如

void* my_alloc1(size_t) __attribute__((assume_aligned(16)))
void* my_alloc2(size_t) __attribute__((assume_aligned(32, 8)))

bnd_instrument 当编译器使用了-fchkp-instrument-marked-only参数项时,此属性下的函数需要被编译器检查边界。
bnd_legacy 当编译器使用了-fcheck-pointer-bounds参数项时,此属性下的函数不需要被编译器检查。
cold 告诉编译器此属性下的函数执行的概率小,重点是优化它的大小而不是执行速度,在许多机器上,它是放在text section下的一个特殊subsection下的,所有在的cold funtion都紧密的放在一齐,用于提高执行速度。
const 禁止函数读取全局变量。

constructor

constructor(priority)

destructor

desctructor(priority)

constructor属性可以使函数在main()执行前被执行,desctructor属性可以使函数在main()执行完成或exit()被调用后执行。

当然可以指定多个,并指定其优先级,对于constructor值越小优先级越大,desctructor值越大优先级越大。

deprecated

deprecated(msg)

如果此属性下的函数在其他地方有被使用,会产生一个warning。

error("message")

warning("message")

如果此属性下的函数被使用,会产生相应的error或warning。
externally_visible 用于全局的变量和函数,会使-fwhole-program失效。
flatten 正常情况下,在一个函数做内联是有限制的,此属性下的函数内,每一个调用都会尽量做内联。
format(archetype,string-index,first-to-check)

使用格式化字符串对函数参数进行检查。archetype可能是printf, scanf, strftime, gun_printf, gnu_scanf, gnu_strftime, strfmon。string-index指定哪个参数进行格式化(从1开始),first-to-check指定在格式化串第一个检查的参数是哪个。例如

extern int
my_printf (void *my_object, const char *my_format, ...)
__attribute__ ((format (printf, 2, 3)));

格式化字符串是my_format是my_printf函数第2个参数,检查的值在const char *my_format中排在第3位。

format-arg(string-index) 指定函数的参数格式化,string-index指定哪个参数被格式化,从1开始。
gnu_inline 此属性下的函数需要有inline关键字,GCC会把函数按gnu90标准处理。
hot 指此函数会被频繁使用,此函数会被gcc更大程序的优化,并且在大部分主机上此函数会放在一个text section的特殊subsection中。
ifunc("resolver")

标识函数是ELF标准下直接使用STT_GNU_IFUNC符号类型扩展的函数。这样符号的解析是函数加载时动态的,要使用这个属性,首先要定义实现的函数和一个选择这个函数的解析函数。例如

void *my_memcpy (void *dst, const void *src, size_t len)
{
...
return dst;
}
static void * (*resolve_memcpy (void))(void *, const void *, size_t)
{
return my_memcpy; // we will just always select this routine
}

然后在用户使用的头文件中声明

extern void *memcpy (void *, const void *, size_t);

然后使用的编译单元内

void *memcpy (void *, const void *, size_t)
__attribute__ ((ifunc ("resolve_memcpy")));

interrupt

interrupt_handler

指定函数是一个中断处理函数
leaf 调用一个有此属性的外部函数时,只能通过return或异常处理才能回到当当前的编译单元。
malloc 标识函数和malloc相似。
no_icf 阻止一个函数与另一个语法上相当的函数合并。
no_intrument_function 当有-finstrument-functions配置项时,大部分用户编译的函数在进入和退出时都会生成profiling function调用,有此属性的函数不会有这个过程。
no_reorder 此属性的函数或变量不会在改变它组装的位置。
no_sanitize("sanitize_option")

此函数不做santize_option指的定的检测,例如

void __attribute__ ((no_sanitize ("alignment", "object-size")))
f (){ /* Do something. */; }

void
__attribute__ ((no_sanitize ("alignment,object-size")))
g (){ /* Do something. */; }

no_sanitize_address

no_address_safety_analysis

当使用-fsanitize=address配置项时,此函数不进入内存访问的检测。

no_sanitize_thread

当使用-fsanitize=thread配置项时,此函数不检测

no_sanitize_undefined

当使用-fsanitize=undefined配置项时,此函数不检测未定义行为。

no_split_stack

当使用-fsplit-stack配置项时,函数可以自己决定是否分隔stack,但是此属性的函数不能他用分隔的stack.

no_stack_limit

此属性的函数进行stack大小检查

noclone

函数不可clone

noinline

函数不可作为inline使用。

noipa

禁止此函数和它的调用者之间进行过程优化。

nonnull(arg-index,...)

函数的参数不能是空指针。例如

extern void *
my_memcpy (void *dest, const void *src, size_t len)
__attribute__((nonnull (1, 2)));

dest和src不能是空指针。

noplt

不使用PLT。例如

/* Externally defined function foo.
int foo () __attribute__ ((noplt));
*/
int
main (/* . . . */)
{
  /* . . . */
  foo ();
  /* . . . */
}

此属性下的函数foo是一个外部函数,调用foo时不避免使用PLT。

noreturn

标识此函数没有返回值。

nothrow

标识此函数不能抛出异常。

optimize

函数使此处指定的优化参数取代command line中的优化参数。

patchable_function_entry

一般情况下,主机下的text segment在运行时是可以写入的,通过在函数入口后增加几个nop可以用于通用工具的检测。

pure

许多函数的返回值只依赖于参数或者全局变量,这样的函数可以使用此属性。

int square (int) __attribute__ ((pure));

returns_nonnull

函数返回值不能是空指针。

returns_twice

函数的返回可能不止一次。

section("section-name")

正常情况下,编译器生成的代码放在text section中。这个属性指定函数编译放置的section。例如

extern void foobar (void) __attribute__ ((section ("bar")));

sentinel

函数调用时,明确指参数是NULL, 只对变参函数有效。

simd

simd("mask")

单指令多数据指令相关。

stack_protect

如果设置了-fstack-protector, -fstack-protector-strong, -fstack-protector-explicit配置顶中,为此属性的函数添加stack protection code。

target(options)

为函数编译指定主机信息。

unused

指示此函数可能是未被使用。

used

表示必须为此函数生成代码。

visibility("visibility_type")

visibility_type有四个值:default, hidden, protected或者internal。

warn_unused_result

此属性的函数被调用,但是返回值未被使用时会产生一个warn.例如

int fn () __attribute__ ((warn_unused_result));
int foo ()
{
if (fn () < 0) return -1;
fn ();
return 0;
}

第5行会生一个warn.

weak

声明一个弱引用符号而不是全局符号。

三、设置变量属性

1、通用属性

aligned(aligment) 内存对齐方式。
warn_if_not_aligned(alignment) 指定一个结构体的阈值,以字节为单位。如果结构的对齐在这个阈值下,会产生warn
cleanup(cleanup_function) 当变量失去作用域时,会调用cleanup_function。

common

nocommon

common修饰的变量会放入“common”存储中,nocommon修饰的变量会直接分配空间。

deprecated

deprecated(msg)

如果此属性下的变量被使用,会产生warn
nostring char、signed char、unsigned char数组在存储时,不需要最后使用NUL结束标志
packed 变量或结构使用最小可能的内存对齐方式。
section("section-name")

指定编译后存储的段

tls_model("tls_model") 使用thread-local存储模式。
unused  标识此变量可能是未被使用的。
used 即使这个变量未被使用,也要生成其代码。

四、设置类型属性

1、通用属性

aligned(alignment) 设置内存对齐方式。
bnd_variable_size 当作用于结构体时,通知Pointer Bounds Checker不要使用静态类型信息来计算其大小。
designated_init 只能用于结构体,表示只能明确的进行初始化,而不能使用位置进行初始化。
scalar_storage_order("endianness") 指定union或struct的大小端存储。
alias("target")  

 




相关推荐

一、概述 GCC一般包括预处理、编译、组装和链接。GCC的运行一般是调用命令gcc,在cross-compiling时使用machine-gcc或machine-gcc-version,在使用c++时

文档对应gcc版本8.4 GCC原来表示GNU C Compiler,现在一脙GNU Compiler Collection。支持C、C++、Objective-C,Objecti

编译器中的sanitize来自于google的开源sanitizers项目,后GNU将该工具加入到GCC编译中,是查找隐藏Bug的利器。 -fsanitize=address</p

一、基本的asm 格式: asm asm-qualifiers ( AssemblerInstructions) (1)asm关键字是GNU的扩展,当编译配置项为-ansi或-std配置项时,使用__

内建函数就是编译器内部实现的函数,它们随时跟着gcc升级而变化,所以不推荐普遍的使用。使用内建函数更高效,因为它们大多以inline方式编译或者针对特定平台进行优化。 C标准库中的

在1999年的ISO C标准中,一个函数可以接收变参数,而宏定义中也可以接收变参数,例如: #define debug(for

强弱符号的链接规则 链接器会按照如下规则处理与选择被多次定义的全局符号 (1)不允许强符号被多次定义,如果有多个强符号定义,则链

一、概述 1、prolog与epilog prolog翻译过来是“序言;开端”。 epilog翻译过来是”后记;结语“。 prolog与epilog其实就是两段固定的代码,当编译器对程序进行编译的时候

在C语言编程过程中,我们常常会实现一些可变参数的函数调用(类scanf、printf函数),变参函数在我们编程过程中带来了很大的方便,但是也有一些问题,即我们在调用可变参数的函数的时候,默认情况

GCC:GNU(Gnu's Not Unix)编译器套装(GNU Compiler Collection,GCC),指一套编程语言编译器,以GPL及LGPL许可证所发行的自由软件