0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

内存泄漏问题原理及检视方法

华为开发者社区 来源:华为开发者社区 作者:华为开发者社区 2020-10-10 10:42 次阅读

可能不少开发者都遇到过内存泄漏导致的网上问题,具体表现为单板在现网运行数月以后,因为内存耗尽而导致单板复位现象。一方面,内存泄漏问题属于比较浅显的错误,此类问题遗漏到现网,影响不好;另一方面,由于内存泄漏问题很可能导致单板运行固定时间以后就复位,只能通过批量升级才能解决,实际影响不佳。本文通过介绍内存泄漏问题原理及检视方法,希望后续能够从编码检视环节就杜绝此类问题发生。

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

01

内存泄漏问题原理

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

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

char *info = NULL; /**转换后的字符串**/ info = (char*)malloc(NB_MEM_SPD_INFO_MAX_SIZE); if( NULL == info) { (void)tdm_error("malloc error! "); return NB_SA_ERR_HPI_OUT_OF_MEMORY; }

由于malloc函数返回的实际上是一个内存地址,所以保存堆内存的变量一定是一个指针(除非代码编写极其不规范)。再重复一遍,保存堆内存的变量一定是一个指针,这对本文主旨的理解很重要。当然,这个指针可以是单指针,也可以是多重指针。 malloc函数有很多变种或封装,如g_malloc、g_malloc0、VOS_Malloc等,这些函数最终都会调用malloc函数。

堆内存的获取方法

看到本小节标题,可能有些同学有疑惑,上一小节中的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_tgetline (char **__lineptr, size_t *__n, FILE *__stream)

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

内存泄漏三要素

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

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

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

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

内存释放误区

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

(1)直接使用内存申请函数申请出来的内存,如malloc、g_malloc等; (2)该开发人员熟悉的接口中,存在内存申请的情况,如iBMC的兄弟,都应该知道调用如下接口需要释放list指向的内存:

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

02

内存泄漏问题检视方法

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

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

(2)分析对局部指针的赋值操作,是否属于前面所说的“两种堆内存获取方法”之一,如果是,就要分析函数返回的指针到底指向啥?是全局数据、静态数据还是堆内存?对于不熟悉的接口,要找到对应的接口文档或源代码分析;又或者看看代码中其它地方对该接口的引用,是否进行了内存释放; (3)如果确认对局部指针存在内存申请操作,就需要分析该内存的去向,是会被保存在全局变量吗?又或者会被作为函数返回值吗?如果都不是,就需要排查函数所有有”return“的地方,保证内存被正确释放。
责任编辑:YYX

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内存
    +关注

    关注

    8

    文章

    2760

    浏览量

    72699
  • C代码
    +关注

    关注

    1

    文章

    88

    浏览量

    14174

原文标题:从原理到方法,一文讲清如何应对C语言内存泄露!

文章出处:【微信号:Huawei_Developer,微信公众号:华为开发者社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言内存泄漏问题原理

    内存泄漏问题只有在使用堆内存的时候才会出现,栈内存不存在内存泄漏问题,因为栈
    发表于 03-19 11:38 145次阅读
    C语言<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>问题原理

    【鸿蒙】webview内存泄漏问题的分析报告

    1 关键字 webview;内存泄漏 2 问题描述 问题现象:在 3.1release 版本和 3.2bete1 版本中,在 RK3568 上使用 etsWeb 和其他浏览器时,webview 所占
    的头像 发表于 03-02 15:12 1587次阅读

    内存溢出与内存泄漏:定义、区别与解决方案

    内存溢出与内存泄漏:定义、区别与解决方案  内存溢出和内存泄漏是计算机科学中常见的问题,在开发和
    的头像 发表于 12-19 14:10 1212次阅读

    如何发现内存泄漏

    检测两个角度介绍在 Linux 环境进行内存泄漏检测的方法,并重点介绍静态分析工具 BEAM、动态监测工具 Valgrind 和 rational purify 的使用方法。相信通过本
    的头像 发表于 11-13 15:41 275次阅读

    线程内存泄漏问题的定位

    记录一个关于线程内存泄漏问题的定位过程,以及过程中的收获。 1. 初步定位 是否存在内存泄漏:想到内存
    的头像 发表于 11-13 11:38 314次阅读
    线程<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>问题的定位

    内存泄漏会产生哪些后果

    内存泄漏原因 内存泄漏在C/C++这种不带GC(Garbage Collection)的语言里,是一个经常发生的问题。因为没有GC,所以分配的内存
    的头像 发表于 11-10 15:06 386次阅读
    <b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>会产生哪些后果

    内存泄漏如何避免

    的数,那就是内存溢出。 2. 内存泄漏 内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的
    的头像 发表于 11-10 11:04 367次阅读
    <b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>如何避免

    什么是内存泄漏?如何避免JavaScript内存泄漏

    JavaScript 代码中常见的内存泄漏的常见来源: 研究内存泄漏问题就相当于寻找符合垃圾回收机制的编程方式,有效避免对象引用的问题。
    发表于 10-27 11:30 124次阅读
    什么是<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>?如何避免JavaScript<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>

    高级内存调试和泄漏检测1.0版

    它可以回答的问题和可以解决的问题包括: ·我使用了多少内存? ·我的代码中哪些部分分配的内存最多? ·是否存在内存泄漏--我在哪里没有释放内存
    发表于 08-28 08:05

    Linux内核内存泄漏怎么办

    在Linux内核开发中,Kmemleak是一种用于检测内核中内存泄漏的工具。
    发表于 07-04 11:04 583次阅读

    细说Linux内存泄漏检测实现原理与实现

    在使用没有垃圾回收的语言时(如 C/C++),可能由于忘记释放内存而导致内存被耗尽,这叫 内存泄漏。由于内核也需要自己管理内存,所以也可能出
    发表于 07-03 09:22 334次阅读
    细说Linux<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>检测实现原理与实现

    Linux内存泄漏检测实现原理与实现

    在使用没有垃圾回收的语言时(如 C/C++),可能由于忘记释放内存而导致内存被耗尽,这叫 内存泄漏
    的头像 发表于 07-03 09:21 423次阅读
    Linux<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>检测实现原理与实现

    记一次Rust内存泄漏排查之旅

    在某次持续压测过程中,我们发现 GreptimeDB 的 Frontend 节点内存即使在请求量平稳的阶段也在持续上涨,直至被 OOM kill。我们判断 Frontend 应该是有内存泄漏了,于是开启了排查
    的头像 发表于 07-02 11:52 414次阅读
    记一次Rust<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>排查之旅

    怎么解决C语言中的内存泄漏问题呢?

    只有在堆内存里面才会发生内存泄漏的问题,在栈内存中不会发生内存泄漏。因为栈
    发表于 06-11 17:31 387次阅读
    怎么解决C语言中的<b class='flag-5'>内存</b><b class='flag-5'>泄漏</b>问题呢?

    gstreamer vpudec内存泄漏如何处理?

    gstreamer vpudec内存泄漏
    发表于 04-21 06:41