__attribute__系列之cleanup

cleanup属性:当变量离开它的作用域时,设置的cleanup_function函数将被调用。

cleanup (cleanup_function)

The cleanup attribute runs a function when the variable goes out of scope. This attribute can only be applied to auto function scope variablesit may not be applied to parameters or variables with static storage durationThe function must take one parameter, a pointer to a type compatible with the variable. The return value of the function (if any) is ignored.

If -fexceptions is enabled, then cleanup_function will be run during the stack unwinding that happens during the processing of the exception. Note that the cleanupattribute does not allow the exception to be caught, only to perform an action. It is undefined what happens if cleanup_function does not return normally.

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

#define local_type  __attribute__ ((cleanup(my_free)))

static void my_free(void* pmem)//the type of paramter must be a void pointer
{
      printf("pmem=%p...\n", pmem);
      printf("&pmem=%p...\n", &pmem);
      void** ppmem = (void**) pmem;
      printf("*ppmem=%p...\n", *ppmem);
      free(*ppmem);
}

#if 0
//warning: passing argument 1 of ‘my_free’ from incompatible pointer type
static void my_free(void** ppmem)
{
      printf("ppmem=%p...\n", ppmem);
      printf("*ppmem=%p...\n", *ppmem);
}
#endif

int foo(void)
{
    local_type int* p = (int*) malloc(sizeof(int));
    printf("do something, p=%p\n", p);

    return 0;
}

int main(int argc, char** argv)
{

    foo();
    // when return, the memory block pointed by p is freed automatically
    printf("11111111\n");

    return 0;
}

利用cleanup属性来实现智能指针:

 1 #include <stdlib.h>
 2 #include <stdio.h>
 3
 4 struct shared_ptr_s
 5 {
 6     //    struct impl_t* inst;
 7     int *use_cnt;
 8 };
 9
10 typedef struct shared_ptr_s shared_ptr_t;           // unadorned type
11 #define shared_ptr struct shared_ptr_s __attribute__((cleanup(free_shared)))
12
13 #define SHARED_PTR_GET_ADD_REF(sp_in, sp_name) ++(*sp_in.use_cnt); 14                         printf("add use_cnt = %d, sp_in=%p\n", *sp_in.use_cnt, sp_in); 15                         shared_ptr sp_name = sp_in; 16                         printf("&sp_name=%p, sp_name:%p\n", &sp_name, sp_name);
17
18 void free_shared(struct shared_ptr_s* ptr)
19 {
20     printf("ptr:%p, usr_cnt:%p\n", ptr, ptr->use_cnt);
21     if(!ptr) return;
22     printf("del use_cnt = %d\n", *ptr->use_cnt - 1);
23     if(0 == --(*ptr->use_cnt)) {
24         //dtor(ptr->inst);
25         printf("freeing %p\n", (void *)ptr->use_cnt);
26         free(ptr->use_cnt);
27     }
28     //ptr->inst = 0;
29     ptr->use_cnt = 0;
30 }
31
32 void func(shared_ptr_t sp)
33 {
34     SHARED_PTR_GET_ADD_REF(sp, sp_loc);
35     printf("111111111\n");
36     return;
37 }
38
39 int main(void)
40 {
41     shared_ptr_t sp = {         // original type does not use __attribute__(cleanup)
42         //.inst = ctor(),
43         .use_cnt = malloc(sizeof(int))
44     };
45     printf("use_cnt content addr:%p, &use_cnt=%p, &sp=%p,sp=%p\n", sp.use_cnt, &sp.use_cnt, &sp,sp);
46     SHARED_PTR_GET_ADD_REF(sp, sp_loc);
47
48     printf("222222222222\n");
49     func(sp_loc);
50     printf("333333333\n");
51
52     return 0;
53 }

运行结果:

use_cnt content addr:0x9ee7008, &use_cnt=0xbfa11dac, &sp=0xbfa11dac,sp=0x9ee7008
add use_cnt = 1, sp_in=0x9ee7008
&sp_name=0xbfa11da8, sp_name:0x9ee7008
222222222222
add use_cnt = 2, sp_in=0x9ee7008
&sp_name=0xbfa11d74, sp_name:0x9ee7008
111111111
ptr:0xbfa11d74, usr_cnt:0x9ee7008
del use_cnt = 1
333333333
ptr:0xbfa11da8, usr_cnt:0x9ee7008
del use_cnt = 0
freeing 0x9ee7008

时间: 2024-08-04 12:30:31

__attribute__系列之cleanup的相关文章

__attribute__系列之介绍篇

1.什么是__attribute__? __attribute__机制是GNU C的一大特色,它可以设置函数属性.变量属性和类型属性等.可以通过它们向编译器提供更多数据,帮助编译器执行优化等. 2.__attribute__语法格式? https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Attribute-Syntax.html#Attribute-Syntax __attribute__ 书写特征是:__attribute__ 前后都有两个下划线,并切后面

__attribute__系列之aligned

__attribute__的属性aligned,作用是为了设置字节对齐. aligned是对 变量和结构体进行 字节对齐的属性设置. 通过aligned属性设置(aligned(对齐字节数)),可以显示的设置对齐字节数,如果使用缺省属性(aligned()),编译器会有一个默认的字节对齐数. aligned特性:aligned属性只能增加对齐字节数,不能减少到比默认对齐字节数还小. aligned支持的最大对齐字节数由linker决定. aligned (alignment) This attr

Objective-C学习笔记:defer的实现方法详解

这篇文章会对 libextobjc 中的一小部分代码进行分析,也是如何扩展 Objective-C 语言系列文章的第一篇,笔者会从 libextobjc 中选择一些黑魔法进行介绍. 对 Swift 稍有了解的人都知道,defer 在 Swift 语言中是一个关键字:在 defer 代码块中的代码,会在作用域结束时执行.在这里,我们会使用一些神奇的方法在 Objective-C 中实现 defer. 如果你已经非常了解 defer 的作用,你可以跳过第一部分的内容,直接看 Variable Att

libextobjc 实现的 defer

算法沉思录:分而治之(复用): 分而治之是指把大而复杂的问题分解成若干个简单的小问题,然后逐个解决.这种朴素的思想来源于人们生活与工作的经验,也完全适合于技术领域. 要崩溃的节奏: 要崩溃的节奏: Variable Attributes libextobjc 实现的 defer 并没有基于 Objective-C 的动态特性,甚至也没有调用已有的任何方法,而是使用了 Variable Attributes 这一特性. 同样在 GCC 中也存在用于修饰函数的 Function Attributes

黑魔法__attribute__((cleanup))

原文地址:http://blog.sunnyxx.com/2014/09/15/objc-attribute-cleanup/ 编译器属性__attribute__用于向编译器描述特殊的标识.检查或优化,几个常用的用法看<mattt大神的文章>就好.今天发现一个名为cleanup的黑魔法属性,简单介绍下. 基本用法 __attribute__((cleanup(...))),用于修饰一个变量,在它的作用域结束时可以自动执行一个指定的方法,如: 1 2 3 4 5 6 7 8 9 // 指定一个

GNU C __attribute__ 机制简介

摘要: 在学习linux内核代码及一些开源软件的源码(如:DirectFB),经常可以看到有关__attribute__的相关使用.本文结合自己的学习经历,较为详细的介绍了__attribute__相关语法及其使用. --------------------------------------------------------- 声明: 此文为原创,欢迎转载,转载请保留如下信息 作者:聂飞(afreez) 北京-中关村 联系方式:[email protected] (欢迎与作者交流) 初次发布

lodash用法系列(3),使用函数

Lodash用来操作对象和集合,比Underscore拥有更多的功能和更好的性能. 官网:https://lodash.com/引用:<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>安装:npm install lodash 首先通过npm安装lodash:npm i --save lodash 在js文件中引用lodash:var _ =

《zw版&#183;Halcon-delphi系列原创教程》 酸奶自动分类脚本(机器学习、人工智能)

<zw版·Halcon-delphi系列原创教程> 酸奶自动分类脚本(机器学习.人工智能) Halcon强大的图像处理能力,令人往往会忽视其更加彪悍的机器学习.人工智能.      至少,目前国内.海外机器学习.人工智能方面的学者,没有几位重视这块.      国外,可能是版权问题,毕竟,Halcon是售价高达数万欧元(不是人民币)的商业软件,而且主要用于自控.机器视觉等工业领域,而不是大学.      国内,可能是对于Halcon的了解不够.      其实,图像处理的核心,图像识别.分类,

Redis系列(1)之安装

Redis系列(1)之安装 由于项目的需要,最近需要研究下Redis.Redis是个很轻量级的NoSql内存数据库,它有多轻量级的呢,用C写的,源码只有3万行,空的数据库只占1M内存.它的功能很丰富,可以将其用作缓存,队列系统等.我们的项目就是用其作为缓存系统.关于Redis的介绍这里就不多说,刚上手完了一会,感觉还不错.那么熟悉Redis就从安装开始. 1. Redis 单机的安装 相比于Hbase的安装,Redis的安装非常简单. 首先从官网上下载安装包,注意Redis的版本规则是次版本(即