电子产业一站式赋能平台

PCB联盟网

搜索
查看: 261|回复: 0
收起左侧

嵌入式软件出现内存泄漏的时候,如何进行排查和分析?

[复制链接]

567

主题

567

帖子

4209

积分

四级会员

Rank: 4

积分
4209
发表于 2025-1-10 17:50:00 | 显示全部楼层 |阅读模式
我是老温,一名热爱学习的嵌入式工程师
0 n  m* m4 `- A) @( d7 t' P/ F2 b关注我,一起变得更加优秀!1.内存泄漏问题原理1.1堆内存在C代码中的存储方式内存泄漏问题只有在使用堆内存的时候才会出现,栈内存不存在内存泄漏问题,因为栈内存会自动分配和释放。C代码中堆内存的申请函数是malloc,常见的内存申请代码如下:/ P( c9 Q  |, T7 {5 J' v: H7 z# n
char *info = NULL;    /**转换后的字符串**/
7 K' K* ~) R$ `* Zinfo = (char*)malloc(NB_MEM_SPD_INFO_MAX_SIZE);# v' T) W$ h" X$ X& A5 X8 Z7 t
if( NULL == info)$ p: t0 ]* A$ r% x# t  g
{# ]5 `: P- H2 X1 `% a& L0 i
    (void)tdm_error("malloc error!; z; ^1 P" l9 ?  l$ {
");
; ^0 C- Y4 l; B    return NB_SA_ERR_HPI_OUT_OF_MEMORY;+ \. |5 E5 w3 ]
}( R8 r5 A4 S# x0 P! o
由于malloc函数返回的实际上是一个内存地址,所以保存堆内存的变量一定是一个指针(除非代码编写极其不规范)。/ B, t. ~0 f* ]- @6 z
再重复一遍,保存堆内存的变量一定是一个指针,这对本文主旨的理解很重要。当然,这个指针可以是单指针,也可以是多重指针。" f* F* ?% V" H" u9 H  z* g7 J
malloc函数有很多变种或封装,如g_malloc、g_malloc0、VOS_Malloc等,这些函数最终都会调用malloc函数。3 ^4 {* i- f& T$ c2 [5 {/ H
1.2堆内存的获取方法看到本小节标题,可能有些同学有疑惑,上一小节中的malloc函数,不就是堆内存的获取方法吗?
4 f: O9 P4 `. C7 `的确是,通过malloc函数申请是最直接的获取方法,如果只知道这种堆内存获取方法,就容易掉到坑里了。一般的来讲,堆内存有如下两种获取方法:/ X5 Z& V0 D3 \! X/ t3 l  t
方法一:将函数返回值直接赋给指针,一般表现形式如下:
, s% ?" @1 R# B& Xchar *local_pointer_xx = NULL;
# S9 S+ Z1 \" x! @. q; _: {1 rlocal_pointer_xx = (char*)function_xx(para_xx, …);# r) L; E- [' Z1 M! K( P6 F
该类涉及到内存申请的函数,返回值一般都指针类型,例如:3 P7 H) p! k3 N9 C2 h
GSList* g_slist_append (GSList   *list, gpointer  data);5 c; A! g3 _+ c2 y! N: j# l& Y/ x0 l
方法二:将指针地址作为函数返回参数,通过返回参数保存堆内存地址,一般表现形式如下:2 B; Z5 O& a0 w) y
int ret;4 @6 H1 F' b* F1 w( I) {
char *local_pointer_xx = NULL;    /**转换后的字符串**/  w1 \; k: |' B: V8 \8 M/ H+ k
ret = (char*)function_xx(..., &local_pointer_xx, ...);0 W$ w" p' M6 v4 F7 s# b
该类涉及到内存申请的函数,一般都有一个入参是双重指针,例如:
- m/ S; j- a5 Z6 `: ~( t, j1 z: |__STDIO_INLINE _IO_ssize_t;
+ L- A/ V2 f, w8 e7 ^5 P! Egetline (char **__lineptr, size_t *__n, FILE *__stream);; g, e3 i5 f# G. e  r
前面说通过malloc申请内存,就属于方法一的一个具体表现形式。其实这两类方法的本质是一样的,都是函数内部间接申请了内存,只是传递内存的方法不一样,方法一通过返回值传递内存指针,方法二通过参数传递内存指针。
  X% I' g# ^7 @- l1.3内存泄漏三要素最常见的内存泄漏问题,包含以下三个要素:
& ]( D2 {+ Y. q' D5 ^" g) \要素一:函数内有局部指针变量定义;
) j9 `4 h! w$ J+ S要素二:对该局部指针有通过上一小节中“两种堆内存获取方法”之一获取内存;9 H1 {0 Y0 E' |
要素三:在函数返回前(含正常分支和异常分支)未释放该内存,也未保存到其它全局变量或返回给上一级函数。2 s! G) X7 o9 ?, _; X
1.4内存释放误区稍微使用过C语言编写代码的人,都应该知道堆内存申请之后是需要释放的。但为何还这么容易出现内存泄漏问题呢?' j) T: C9 a; h8 X
一方面,是开发人员经验不足、意识不到位或一时疏忽导致;另一方面,是内存释放误区导致。很多开发人员,认为要释放的内存应该局限于以下两种:
$ B9 R2 s- N4 H5 b7 t$ o% d1) 直接使用内存申请函数申请出来的内存,如malloc、g_malloc等;5 n+ d" c7 u, W+ t* q0 g  Y
2)该开发人员熟悉的接口中,存在内存申请的情况,如iBMC的兄弟,都应该知道调用如下接口需要释放list指向的内存:$ f/ N* t: }3 D% D* R2 E, L
dfl_get_object_list(const char* class_name, GSList **list);7 @* D* o9 g2 l
按照以上思维编写代码,一旦遇到不熟悉的接口中需要释放内存的问题,就完全没有释放内存的意识,内存泄漏问题就自然产生了。
  |' S4 C3 O  ^+ [2.内存泄漏问题检视方法检视内存泄漏问题,关键还是要养成良好的编码检视习惯。与内存泄漏三要素对应,需& \0 R+ s" q9 x% d8 K
要做到如下三点:8 V3 F) J( b% U9 a
1) 在函数中看到有局部指针,就要警惕内存泄漏问题,养成进一步排查的习惯
) n! l2 z2 E7 A" f1 q2) 分析对局部指针的赋值操作,是否属于前面所说的“两种堆内存获取方法”之一,如果是,就要分析函数返回的指针到底指向啥?
9 f+ ]" r" e) l是全局数据、静态数据还是堆内存?对于不熟悉的接口,要找到对应的接口文档或源代码分析;又或者看看代码中其它地方对该接口的引用,是否进行了内存释放;& J  x, K7 g: }- e& m& o
3) 如果确认对局部指针存在内存申请操作,就需要分析该内存的去向,是会被保存在全局变量吗?又或者会被作为函数返回值吗?如果都不是,就需要排查函数所有有”return“的地方,保证内存被正确释放。9 O. f4 Y3 {9 V2 X
原文:https://my.oschina.net/u/4526289/blog/4539592) Q& P9 x- B' ]9 B3 R: V

# p2 {) E  f7 E0 Z9 x( Y-END-* |8 e* F4 x+ e. ~" n4 |* w$ ^
往期推荐:点击图片即可跳转阅读* d7 {! T7 R+ k3 B

$ J, R( i1 K3 J                                                       
3 b$ \' @& q0 T3 b) s7 d( S9 R                                                               
! z' n( i6 w2 W# V                                                                       
, ?1 w5 n7 a) t2 a- M  v                                                                                4 x0 f$ o' W; e* ]& i) P

irze1x03bu164051385505.jpg

irze1x03bu164051385505.jpg
0 e0 s' _. F3 U/ A9 L6 r
                                                                               
2 r0 J3 K; U8 T7 w& N# @                                                                                        2025年,抽屉里的嵌入式开发板,早就已经写满了岁月的痕迹!, n% j$ n: R. e3 c2 u9 `
                                                                                2 F3 Z8 o1 a% C- R
                                                                        1 \8 {0 ^, @7 v/ [" r3 n
                                                               
/ I# d6 }; @$ C/ f: z  D                                                        & f8 d) E0 W, W8 x
                                                , X" {2 h8 K1 q( B& F/ W5 ^
( L/ ]: K, G: L
                                                       
. l' C1 h4 \; W3 e                                                               
7 ~$ F. `7 y$ M/ N' x                                                                        " [$ t1 |. [7 s# N) \
                                                                                0 t- N" c) l- m

kkdmnu4ouj564051385605.jpg

kkdmnu4ouj564051385605.jpg

2 C: d6 {% R! Y7 ]6 {                                                                               
( Y7 U: o- h/ b' u                                                                                        一些不太成熟的嵌入式系统设计观念!
8 D5 b! w0 L) E7 V' [" q                                                                                3 Y5 T4 r; W7 Z
                                                                       
0 [6 a9 j) F5 z5 j, Z' [: W                                                               
9 c) N& N& U( q: ^: ]2 t  `                                                       
6 o" N  @: \! Y0 U; c                                               
% M9 n) y4 W) P9 @
7 q* A5 C& \; U3 J; M9 {9 x                                                       
, F7 k; Y# u4 G1 I                                                               
/ J" i3 t& w. F1 l( {4 v                                                                        4 e. b9 d* u& |- w/ I0 N
                                                                               
1 j) G) l% Q+ f( U$ ]5 U

345wlygzsfk64051385705.jpg

345wlygzsfk64051385705.jpg
% z% j' e' ~. w
                                                                               
# e! t( x+ U6 g+ {, p9 Q                                                                                        嵌入式软件OTA升级,有哪几种FLASH划分方式?
- c, S: f, y1 S6 y" u* A                                                                                0 n! P- R# n/ l5 F, t& h2 ?9 c) n9 b
                                                                        2 N7 q% v* j- L: C' G
                                                                7 T1 S( t, J5 A* A8 l- I' a, n! c
                                                       
+ n1 ]  |2 u: u" }  \                                                8 e" g, u2 ~! m5 ?3 Q4 p+ N, p
我是老温,一名热爱学习的嵌入式工程师
' Z' x( p) o( F! j, S% ?/ n; }+ o关注我,一起变得更加优秀!* E; R) @8 r. J, [- Y2 G6 L

0zgnxu5mfff64051385806.png

0zgnxu5mfff64051385806.png
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表