c c++函数资源释放时避免goto的方法

开发C/C++模块时,因为很多内存资源都需要自己释放,为了统一一个地方释放资源通常用goto标签在函数退出时释放资源,好处是资源统一释放,不会因为在提前return时分别释放资源导致以后修改代码遗漏释放某些资源导致死锁或者内存泄漏。

以下是goto模式

void goto_function() {char *buf = NULL;buf = (char *)malloc(64 * sizeof(char));if (NULL == buf) {goto LABEL_EXIT;}snprintf(buf, 64, "Hello goto function");printf("%s\n", buf);LABEL_EXIT:if (NULL != buf) {free(buf);buf = NULL;}return;
}

这是比较简单的goto代码,所以看起来没那么别扭。假如我们用在修改代码如下:

void goto_function() {char *buf = NULL;buf = (char *)malloc(64 * sizeof(char));if (NULL == buf) {goto LABEL_EXIT;}size_t len = 0; // 在goto 的label第一次使用之后,声明临时变量snprintf(buf, 64, "Hello goto function");len = strlen(buf);printf("%s\n", buf);LABEL_EXIT:if (NULL != buf) {free(buf);buf = NULL;}return;
}

编译会出现如下错误

$ g++ main.cpp

main.cpp:9:3: error: cannot jump from this goto statement to its label

goto LABEL_EXIT;

^

main.cpp:11:9: note: jump bypasses variable initialization

size_t len = 0; // 在goto 的label第一次使用之后,声明临时变量

^

1 error generated.

如果在goto第一次使用之后,那么不能继续创建临时变量了。因为label不知道在label第一次使用之后的临时变量。要修改需要把临时变量的声明放在goto label之前

void goto_function() {size_t len = 0; // 在goto 的label第一次使用之前,声明临时变量char *buf = NULL;buf = (char *)malloc(64 * sizeof(char));if (NULL == buf) {goto LABEL_EXIT;}snprintf(buf, 64, "Hello goto function");len = strlen(buf);printf("%s\n", buf);LABEL_EXIT:if (NULL != buf) {free(buf);buf = NULL;}return;
}

再编译就相安无事。

变量在函数头集体申明其实非常不利于代码的可读性,不利于查看临时变量的类型,增加冗余代码行,不能尽量让局部变量变量声明和定义放在一处执行,为了避免这种情况,我们需要规避goto带来的弊端,可以用 do while配合break

void none_goto_function() {char *buf = NULL;do {buf = (char *)malloc(64 * sizeof(char));if (NULL == buf) {break;}snprintf(buf, 64, "Hello none goto function");size_t len = 0; // 在do while内声明临时变量len = strlen(buf);printf("%s\n", buf);} while(0);if (NULL != buf) {free(buf);buf = NULL;}return;
}

这里利用了do while的break特性降解goto带来的无法邻近声明局部变量的弊端。不过只是暂时规避而已,因为break也是有缺点的,当do while内的循环或者switch也用到了break,这时候也会降低break程序的可读性。例如:

void none_goto_nest_break_function() {char *buf = NULL;do {buf = (char *)malloc(64 * sizeof(char));if (NULL == buf) {break; // break out of do while}for (int i = 0; i < 5; i++) {if (i == 3) {break; // break out of for loop}}snprintf(buf, 64, "Hello none goto function");printf("%s\n", buf);} while(0);if (NULL != buf) {free(buf);buf = NULL;}return;
}

对付这种情况可以尽量将for循环内的代码用函数封装,大部分循环内代码都能够抽象为一个简单的函数。

PS: 不过抽象为函数又会影响执行性能,总之也不是终极解决方案。

c c++函数资源释放时避免goto的方法相关推荐

  1. rhcs做HA时的资源释放脚本实现

    场景: CentOS6.3的二次封装版本,安装hortonworks的hadoop发行版,并按照其官方文档实现高可用,但无fence设备支持,因此导致断网和断电测试时,备用HA节点无法得到资源释放的通 ...

  2. Linux 释放socket资源,LwIP使用select,close socket资源释放不完全问题

    这篇文章本应该在4月就写好的,但是博客评论系统一直没有搭建好,走了很多弯路,现在好了,delay这么久,终于要要补过来了.自建博客:金宝的博客 该文章完全原创,除通用.广泛的知识点外,均为个人总结,如 ...

  3. C#中的非托管资源释放(FinalizeDispose)

    在了解Finalize和Dispose之前,我们需要了解两个概念,一个是托管资源,一个非委托资源. a.其中托管资源一般是指被CLR控制的内存资源,这些资源的管理可以由CLR来控制,例如程序中分配的对 ...

  4. c#中的非托管资源释放 (Finalize和Dispose)

    c#中的非托管资源释放 (Finalize和Dispose) 收藏 在了解Finalize和Dispose之前,我们需要了解两个概念,一个是托管资源,一个非委托资源. a.其中托管资源一般是指被CLR ...

  5. VC++ - 各种DC及DC资源释放

    2013-04-18 16:58:57|  分类: GDI |  标签:cclientdc与cpaintdc  dc释放  dc  |字号 订阅 CClientDC dc(this); CPaintD ...

  6. Java8 新的 try-with-resources 语句,自动资源释放

    读取文件后需要释放资源,对于占用内存比较大的,非常重要: (1)读取文件内存占用较多的优化方式: 一次读取部分处理完继续读取,可以有效的减少内存的占用: 使用RandomAccessFile可以从文件 ...

  7. 基于 Android NDK 的学习之旅-----资源释放

    基于 Android NDK 的学习之旅-----资源释放 做上一个项目的时候因为与C引擎交互频繁,有时候会突然莫名其妙的的整个应用程序直接挂掉.因为我是学Java 开始的,所以对主动释放内存没多大概 ...

  8. qt中关闭窗口资源释放问题

    针对QDialog对象,如果是栈上分配的,就不存在资源泄漏问题,但是当对象是new出来的,并且以局部对像存在,当关闭时,窗口只是隐藏,资源是没有释放的,每次exec后者需要delete来释放,另外一种 ...

  9. C#内存泄露与资源释放 经验总结

    本文链接:http://blog.csdn.net/yokeqi/article/details/41083939 C#相比其他语言,拥有强大的垃圾回收机制,但并不是这样,你就可以对内存管理放任不管, ...

  10. c#自定义控件资源释放问题_定义资源

    c#自定义控件资源释放问题 在Fielding的论文中 ,资源描述为: "可以命名的任何信息"--"文档或图像,临时服务(例如,"洛杉矶今天的天气") ...

最新文章

  1. 嵌入式新人发展的总体方向
  2. 光流 | 基于对偶方法的变分光流改进算法
  3. RequestBody获取前端数据_360视频云Web前端HEVC播放器实践剖析
  4. opencv 最大连通域_opencv 查找连通区域 最大面积实例
  5. AT2370-[AGC013D]Piling Up【dp】
  6. .net中如何发送HTTP请求网络资源
  7. JDBC连接池和DBUtils
  8. ICCV2021 香港理工、阿里达摩院提出RealVSR:视频超分任务中的新数据集与损失方案...
  9. MTK MT2503 11B讲义-01编译
  10. 理解PPAPI的设计
  11. Mac剪贴板复制粘贴内容管理: Paste
  12. 撰写科技论文的意义-李正海
  13. WORD 或者 Outlook 提示“无法创建工作文件,请检查临时环境变量” 的解决方法
  14. TCP/IP路由技术(第1卷)(第2版) + TCP/IP路由技术(第2卷)(第2版)
  15. 微信公众号嵌套html,VUE项目嵌入微信公众号文章URL
  16. 【CSS3】Advanced1:Rounded Corners
  17. 关于插画师,大家不知道的“秘密”
  18. java excel 数据有效性_Excel设置数据有效性实现单元格下拉菜单的3种方法
  19. 6-3 sdust-Java-模拟主板、USB口、TypeC口、PS2口设备 (20 分)
  20. 亲测快捷高效的编写测试用例方法

热门文章

  1. 240.搜索二维矩阵II(力扣leetcode) 博主可答疑该问题
  2. 爬虫爬取免费代理ip,验证代理ip有效性,保存到本地txt,建立代理池
  3. matlab中找不到指定的模块,Matlab装好后启动提示找不到指定模块如何解决?很急...
  4. android卡机字符串,Android调用replace方法正则表达式卡死
  5. Linux -- file 命令
  6. vant实现三级联动
  7. Jenkins集群搭建
  8. celery 4.1下报kombu.exceptions.EncodeError: Object of type 'bytes' is not JSON serializable 处理方式...
  9. 【字符串】 - 判断是否包含相应的字符 - 截取某一部分字符
  10. 利用图片延迟加载来优化页面性能(jQuery)