C语言内存泄漏问题及其检视方法

点击蓝字

8493f93b1a8589a907079970f3040058.png

关注我们

来源于网络,侵删

通过介绍内存泄漏问题原理及检视方法,希望后续能够从编码检视环节就杜绝内存泄漏导致的网上问题发生。

    本文通过介绍内存泄漏问题原理及检视方法,希望后续能够从编码检视环节就杜绝此类问题发生。

    预防内存泄漏问题有多种方法,如加强代码检视、工具检测和内存测试等,本文聚集于开发人员能力提升方面。

内存泄漏问题原理

1 堆内存在C代码中的存储方式


内存泄漏问题只有在使用堆内存的时候才会出现,栈内存不存在内存泄漏问题,因为栈内存会自动分配和释放。C语言代码中堆内存的申请函数是malloc,常见的内存申请代码如下:

12d82846f31eb2c67df4e2a14e2987d1.png

    由于malloc函数返回的实际上是一个内存地址,所以保存堆内存的变量一定是一个指针(除非代码编写极其不规范)。再重复一遍,保存堆内存的变量一定是一个指针,这对本文主旨的理解很重要。当然,这个指针可以是单指针,也可以是多重指针。

    malloc函数有很多变种或封装,如g_malloc、g_malloc0、VOS_Malloc等,这些函数最终都会调用malloc函数。

2 堆内存的获取方法

    看到本小节标题,可能有些同学有疑惑,上一小节中的malloc函数,不就是堆内存的获取方法吗?的确是,通过malloc函数申请是最直接的获取方法,如果只知道这种堆内存获取方法,就容易掉到坑里了。

    一般的来讲,堆内存有如下两种获取方法:

「方法一:将函数返回值直接赋给指针,一般表现形式如下:」

char *local_pointer_xx = NULL;
local_pointer_xx = (char*)function_xx(para_xx, …);

    该类涉及到内存申请的函数,返回值一般都指针类型,例如:

GSList* g_slist_append (GSList   *list, gpointer  data)

「方法二:将指针地址作为函数返回参数,通过返回参数保存堆内存地址,一般表现形式如下:」

int ret;
char *local_pointer_xx = NULL;    /**转换后的字符串**/
ret = (char*)function_xx(..., &local_pointer_xx, ...);

    该类涉及到内存申请的函数,一般都有一个入参是双重指针,例如:

__STDIO_INLINE _IO_ssize_t
getline (char **__lineptr, size_t *__n, FILE *__stream)

    前面说通过malloc申请内存,就属于方法一的一个具体表现形式。其实这两类方法的本质是一样的,都是函数内部间接申请了内存,只是传递内存的方法不一样,方法一通过返回值传递内存指针,方法二通过参数传递内存指针。

3 内存泄漏三要素

    最常见的内存泄漏问题,包含以下三个要素:

**要素一:**函数内有局部指针变量定义;

**要素二:**对该局部指针有通过上一小节中“两种堆内存获取方法”之一获取内存;

**要素三:**在函数返回前(含正常分支和异常分支)未释放该内存,也未保存到其它全局变量或返回给上一级函数。

4 内存释放误区

    稍微使用过C语言编写代码的人,都应该知道堆内存申请之后是需要释放的。但为何还这么容易出现内存泄漏问题呢?一方面,是开发人员经验不足、意识不到位或一时疏忽导致;另一方面,是内存释放误区导致。很多开发人员,认为要释放的内存应该局限于以下两种:

1)直接使用内存申请函数申请出来的内存,如malloc、g_malloc等;

2)该开发人员熟悉的接口中,存在内存申请的情况,如iBMC的兄弟,都应该知道调用如下接口需要释放list指向的内存:

dfl_get_object_list(const char* class_name, GSList **list)

    按照以上思维编写代码,一旦遇到不熟悉的接口中需要释放内存的问题,就完全没有释放内存的意识,内存泄漏问题就自然产生了。

内存泄漏问题检视方法

    检视内存泄漏问题,关键还是要养成良好的编码检视习惯。与内存泄漏三要素对应,需

    要做到如下三点:

(1)在函数中看到有局部指针,就要警惕内存泄漏问题,养成进一步排查的习惯

(2)分析对局部指针的赋值操作,是否属于前面所说的“两种堆内存获取方法”之一,如果是,就要分析函数返回的指针到底指向啥?是全局数据、静态数据还是堆内存?对于不熟悉的接口,要找到对应的接口文档或源代码分析;又或者看看代码中其它地方对该接口的引用,是否进行了内存释放;

(3)如果确认对局部指针存在内存申请操作,就需要分析该内存的去向,是会被保存在全局变量吗?又或者会被作为函数返回值吗?如果都不是,就需要排查函数所有有”return“的地方,保证内存被正确释放。

214522d38e1243165886e43c04d61d6e.gif

如果你年满18周岁以上,又觉得学【C语言】太难?想尝试其他编程语言,那么我推荐你学Python,现有价值499元Python零基础课程限时免费领取,限10个名额!
▲扫描二维码-免费领取

2368d9e5c0d96c0a5c176e08c6d8df9d.gif

戳“阅读原文”我们一起进步

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337262.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

未定义与 struct 类型的输入参数相对应的函数 fetch_引入鲁棒性作为连续参数,这种新损失函数实现了自适应、随时变换...

编辑:陈萍损失函数是机器学习里最基础也是最为关键的一个要素,其用来评价模型的预测值和真实值不一样的程度。最为常见的损失函数包括平方损失、指数损失、log 对数损失等损失函数。这里回顾了一种新的损失函数,通过引入鲁棒性作为连续参数&a…

清理jdk注册表_JDK 9早期版本安装后的Windows注册表清理

清理jdk注册表在我的上一篇博文中 ,我演示了在安装早期版本的JDK 9(内部版本68)之后围绕Oracle Java符号链接 (基于Windows的计算机上的C:\ProgramData\Oracle\Java\javapath\目录)的问题的解决方案。这似乎阻止了早期…

汇编语言调用C语言/C++实例:乘法表

点击蓝字关注我们来源于网络,侵删现在编写一个简单的应用程序,提示用户输入整数,通过移位的方式将其与 2 的幕 (2〜2ⁿ) 相乘,并用填充前导空格的形式再次显示每个乘积。输入-输出使用 C。汇编模块将调用 3 个 C 编写的函数。程序…

rect函数_R函数不会写,quot;抄quot;总会吧!

前面我们简单的介绍了R函数。有些人可能会说,我现在的R水平有限,还不足以写出很高级的函数,该怎么办?俗话说前人栽树后人乘凉,他山之石可以攻玉,鲁迅同志也提出过“拿来”主义。已经有前人,高手…

10个超赞的C语言开源项目,强烈推荐!

点击蓝字关注我们来源于网络,侵删今天分享10个超赞的C语言开源项目,希望这些内容能对大家有所帮助!目录:1. Webbench2. Tinyhttpd3. cJSON4. CMockery5. Libev6. Memcached7. Lua8. SQLite9. UNIX v610. NETBSD1. WebbenchWebbenc…

jboss性能指标_JBoss BRMS复杂事件处理(CEP)性能基准

jboss性能指标技术来了又去,但是一件事保持不变。 在设计企业解决方案时,我们喜欢使我们的生活更轻松的复杂组件,作为建筑师和开发人员,我们一直在寻找使我们的生活更轻松的方法。 一种方法是跟上与感兴趣的技术有关的流行新站点…

C语言经验分享:二维指针与二维数组的两种错误用法

点击蓝字关注我们来源于网络,侵删引子首先看一段代码:void test(int *p) {}int main() {int arr[] {30, 450,14,5};test(arr);return 0; }毫无疑问,上面这段代码是运行OK的。因为C语言标准中有以下规则:在函数参数的声明中,数组名被编译器当作…

camel 使用_使用Camel从WildFly 8向WebLogic 12发送JMS消息

camel 使用系统集成是一个很好的挑战。 特别是当您在寻找通信标准和可靠的解决方案时。 在当今的微服务世界中,每个人都在谈论REST服务和基于http的协议。 实际上,对于大多数通常具有更复杂的需求集的大多数企业项目来说,这是远远不够的。 合…

C++异常处理控制流下的OLLVM混淆

点击蓝字关注我们来源于网络,侵删Inflated!!!C异常化处理OLLVM-控制流平坦化Two PuzzlesException一般碰到C异常逆向,确定了异常分发、处理部分,直接把call throw改为jmp catch块,再F5即可。PS: 多个catch块根据rdx来当为异常处理…

【微服务】springboot整合kafka-stream使用详解

目录 一、前言 二、kafka stream概述 2.1 什么是kafka stream 2.2 为什么需要kafka stream 2.2.1 对接成本低 2.2.2 节省资源 2.2.3 使用简单 2.3 kafka stream特点 2.4 kafka stream中的一些概念 2.5 Kafka Stream应用场景 三、环境准备 3.1 搭建zk 3.1.1 自定义d…

C语言知识总结一:C语言的基本知识汇总

点击蓝字关注我们来源于网络,侵删C语言是一种计算机程序设计语言。它既有高级语言的特点,又具有汇编语言的特点。它可以作 为系统设计语言,编写工作系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机 硬件的应…

jboss8日志级别设置_罐中研讨会:设置JBoss BPM Suite全日研讨会

jboss8日志级别设置是否在寻找一种简单的方法来宣传,展示或演示JBoss业务流程管理套件(BPM Suite)产品的入门难度? 别无所求,因为我们已经召集了这个研讨会,因此您可以围绕JBoss BPM Suite构建一个晚上&a…

yapi 接口文档_1分钟docker部署顶尖 API 文档管理系统

YApi 是高效、易用、功能强大的 api 管理平台,旨在为开发、产品、测试人员提供更优雅的接口管理服务。可以帮助开发者轻松创建、发布、维护 API,YApi 还为用户提供了优秀的交互体验,开发人员只需利用平台提供的接口数据写入工具以及简单的点击…

微软CTO建议业界弃用C/C++采用Rust,遭C++之父回怼

点击蓝字关注我们来源于网络,侵删近日,Microsoft Azure CTO、Sysinternals 的主要开发者 Mark Russinovich 在其社交账号上发布动态称,开发人员是时候停止使用 C/C 来启动新项目,并建议可在需要使用 non-GC 语言的场景中使用 Rust…

红帽 jboss_红帽峰会2015所需的JBoss BPM内容指南

红帽 jboss明年再见? 今年在Red Hat Summit上,我们在JBoss BRMS和JBoss BPM Suite演讲中获得了很多乐趣。 在DevNation周围也有一些社区会议,重点介绍了使我们的产品成为可能的项目。 您可以在他们的博客上找到此演讲的概述,并…

Python、C、Java 和 C++ 四足鼎立,其他已无胜算? | TIOBE 10 月编程语言排行榜

点击蓝字关注我们来源于网络,侵删技术的千变万化,都是有迹可循的,最新的 TIOBE 十月编程语言榜单重磅发布,快来看看有哪些值得关注的变化吧!四大编程语言不断增强其主导地位曾几何时,编程语言界中 Java、C、…

C语言 #define 和 typedef 区别

点击蓝字关注我们来源于网络,侵删在C语言编程中,typedef 和 #define是最常用语句,可能很多工作过几年的工程师都没有去深究过它们的一些用法和区别。typedef的用法在C/C语言中,typedef常用来定义一个标识符及关键字的别名&#xf…

Spring Batch –用JavaConfig替换XML作业配置

最近,我协助一个客户启动并运行了Spring Batch实现。 该团队决定继续使用针对批处理作业的基于JavaConfig的配置,而不是传统的基于XML的配置。 随着这越来越成为配置Java应用程序的一种常用方法,我觉得是时候更新Keyhole的Spring Batch系列了…

sql limit 子句_Java 8流中的常见SQL子句及其等效项

sql limit 子句功能编程允许使用通用语言进行准声明性编程 。 通过使用功能强大的流畅API(例如Java 8的Stream API )或jOOλ的顺序Stream扩展Seq或更复杂的库(例如javaslang或functionaljava) ,我们可以以一种非常简洁…

C++编程中的核心知识点!

点击蓝字关注我们来源于网络,侵删尊重函数接口,尽量不作内部改动C代码语句分为:内置类型,名字,变量,操作符,标量,字符串,预处理指示(如#include)等…