Playing with __attributes__ (一)

前言

在一些代码中我们经常能看见如下的一些函数修饰符:

__attribute__((constructor)) static void foo(void) {
    //...
}
void f(void) __attribute__((availability(macosx,introduced=10.4,deprecated=10.6,obsoleted=10.7)));

起源

GNU C中,我们可以使用函数属性(Function attribute)为我们的函数定义特定的编译器优化、编译器检查、内存管理、代码生成、调用返回转换。
比如:noreturn用于指定该函数没有返回值。format用于指定函数参数中存在打印编码风格的参数。

很多属性是平台相关的,比如很多平台支持interrupt,但具体使用时必须遵从特定平台的寄存器使用规范。

__declspec(dllimport) 就是一个常见的在Windows下用于声明从动态库引入函数的声明。

函数属性使用__attribute__作为声明关键字,其后用双括号(())指定一个特定的属性,使用逗号,间隔多个属性。具体可参见Attribute Syntax

常用的函数属性

constructor

其修饰的函数将在装载Binary的时候调用,在macos 的call stack如下:

    frame #1: 0x00007fff5fc12d0b dyld`ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 265
    frame #2: 0x00007fff5fc12e98 dyld`ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 40
    frame #3: 0x00007fff5fc0f891 dyld`ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 305
    frame #4: 0x00007fff5fc0f718 dyld`ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 138
    frame #5: 0x00007fff5fc0f989 dyld`ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 75
    frame #6: 0x00007fff5fc02245 dyld`dyld::initializeMainExecutable() + 187
    frame #7: 0x00007fff5fc05c19 dyld`dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 2669
    frame #8: 0x00007fff5fc01276 dyld`dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*) + 512
    frame #9: 0x00007fff5fc01036 dyld`_dyld_start + 54

多个constructor函数调用顺序由声明顺序决定

destructor

同理在程序结束时调用。

constructor && destructor with PRIORITY

语法:__attribute__((destructor (PRIORITY)))
PRIORITY越小,优先级越高,越早调用
如:

void begin_0 (void) __attribute__((constructor (101)));
void end_0 (void) __attribute__((destructor (101)));
void begin_1 (void) __attribute__((constructor (102)));
void end_1 (void) __attribute__((destructor (102)));
void begin_2 (void) __attribute__((constructor (103)));
void end_2 (void) __attribute__((destructor (103)));

运行结果:

begin_0 ()
begin_1 ()
begin_2 ()
end_2 ()
end_1 ()
end_0 ()

returns_nonnull

告知编译器返回值绝不为NULL

alias (“target”)

为函数定义别名

其他

除了函数属性(Function Attributes)还有 Variable Attributes, Type Attributes, Label Attributes, Enumerator Attributes等.

Clang对iOS有专用的attributes,戳这里.下期再详述

参考阅读

1
2

原作写于segmentfault 链接

    原文作者:canopus4u
    原文地址: https://segmentfault.com/a/1190000003887934
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞