1、HUAWEI TECHNOLOGIES CO., LTD. Huawei Confidential Security Level: Internal PC语言软件编程规范工作组公司常见软件编程低级错误:内存泄漏Page 2Huawei Confidential HUAWEI TECHNOLOGIES CO., LTD.前言 这套材料作为编程规范的辅助材料,帮助大家理解编程规范背后的原理。 C和 C+语言是我司的主流编程语言,然而 C/C+具有很多强大的语言特性,从而导致 C/C+非常复杂,使得代码更容易出现 BUG、难以阅读和维护。 业界知名的编程规范都对 C/C+容易出现问题的语言特性进行管
2、理。例如 MISRA(汽车工业软件可靠性联合会)制定的 1998版的 MISRAC规范指出,一些在 C看来可以接受,却存在隐患的地方有 127处之多。 2004版的 MISRAC规范将针对 C语言的规则增加到了 141条。 对于程序员来说,能工作的代码并不等于 “好 ” 代码。 “好 ”代码的指标很多,包括可读性、可维护性、可移植性和可靠性等。出现网上问题的代码,大多数是不良编程习惯引起的。不遵守编程规范的代码,往往也是最不可靠的代码。 本胶片收集了常见的内存泄漏案例,给出了相应的纠正措施。对应的编程规范:防止内存泄漏;函数中分配的内存,在函数退出之前要释放Page 3Huawei Confi
3、dential HUAWEI TECHNOLOGIES CO., LTD.内存泄漏案例问题和纠正措施建议Page 4Huawei Confidential HUAWEI TECHNOLOGIES CO., LTD.异常出口处没有释放内存【 问题描述 】 代码飞检发现如下代码:pMsgDB_DEV = (PDBDevMsg)GetBuff( sizeof( DBDevMsg ), _LINE_);if( pMsgDB_DEV = NULL ) return; pMsgDBApp_To_Logic = (LPDBSelfMsg)GetBuff( sizeof(DBSelfMsg), _LINE_
4、);if( pMsgDBApp_To_Logic = NULL ) return;【 问题定位 】 在第 2个 return处, pMsgDB_DEV指向的内存丢失Page 5Huawei Confidential HUAWEI TECHNOLOGIES CO., LTD.异常出口处没有释放内存 (续 1)【 问题描述 】 代码飞检发现如下代码:/* 在 AVL树中添加节点 */IF_VC_AVL_AddNode( if (ulRet != VOS_OK ) /* 创建 VC控制块失败 */ return; 【 问题定位 】 创建 VC控制块失败时, return前没有删除 AVL树中的节点【
5、 举一反三 】 看见 return要注意,要去前面找资源,特别要注意链表等数据结构中的资源Page 6Huawei Confidential HUAWEI TECHNOLOGIES CO., LTD.异常出口处没有释放信号量资源【 问题描述 if(rc != NP_RC_SUCCESS)/*申请信号量失败 */NP_SS_ASSERT(0, “Create qinq sem failed!“);return rc; #if SOFT_Versionrc = np_ss_semB_create(NP_SEM_EMPTY, NP_SEM_Q_FIFO, if(rc != NP_RC_SUCCESS
6、)/*申请信号量失败 */NP_SS_ASSERT(0, “Create qinq sem failed!“);return rc; /没有释放前面分配的信号量 g_ims_vport_base_info.qinq_base_info.sem #endif .NP_FREE_SEM(g_ims_vport_base_info.qinq_base_info.sem);#if SOFT_VersionNP_FREE_SEM(g_ims_vport_base_info.eqinq_base_info.sem);#endif return rc;Page 7Huawei Confidential HU
7、AWEI TECHNOLOGIES CO., LTD.异常出口处没有释放信号量资源(续)【 纠正措施 】 第二个信号量申请失败 return之前释放第一个申请的信号量。#if SOFT_Versionrc = np_ss_semB_create(NP_SEM_EMPTY, NP_SEM_Q_FIFO, if(rc != NP_RC_SUCCESS)/*申请信号量失败 */NP_SS_ASSERT(0, “Create qinq sem failed!“);NP_FREE_SEM(g_ims_vport_base_info.qinq_base_info.sem);return rc; #endi
8、f。 【 举一反三 】 看见 return要注意,要去前面找资源,特别要注意信号量、定时器等资源Page 8Huawei Confidential HUAWEI TECHNOLOGIES CO., LTD.异常出口处没有释放 GUI资源【 问题描述 】 网上问题案例:CBitmap bmp;CBitmap* pOldBmp; bmp.LoadBitmap(IDB_MYBMP);pOldBmp = pDC-SelectObject( if( Something() ) return; pDC-SelectObject( pOldBmp );【 问题定位 】 return前没有调用 SelectO
9、bject()把 pOldBmp选回 pDC中,这会导致 pOldBmp指向的 HBITMAP对象发生泄漏。这个程序如果长时间的运行,会导致系统花屏【 举一反三 】 除了申请的内存外,系统提供的其它资源,如文件句柄 /Socket/队列等也是资源,使用完毕必须释放Page 9Huawei Confidential HUAWEI TECHNOLOGIES CO., LTD.没有释放结构的成员指针【 问题描述 】 网上问题案例:struct STORE_BUF_SULONG ulLen;UCHAR *pcData;STORE_BUF_T;void func()STORE_BUF_T *pstSto
10、rageBuff = NULL;/申请结构内存/程序处理。free(pstStorageBuff);return;删除了 pstStorageBuff,但 pstStorageBuff-pcData没有删除。【 问题定位 】 先删除了 pstStorageBuff, pstStorageBuff-pcData永远不可能被删除了 【 举一反三 】 删除结构指针时,必须从底层向上层顺序删除 Page 10Huawei Confidential HUAWEI TECHNOLOGIES CO., LTD.没有释放数组的成员指针【 问题描述 】 测试部对 M产品进行压力和稳定性测试,模拟文件上传的场景,
11、把本地目录下的 3万个文件上传到另一台主机。发现上传程序在传送文件过程中,内存在快速增长,通过 ps auwx监控,发现该进程占用的内存每隔 4分钟(一个周期)就突然增加 20 30M的内存。【 问题定位 】 struct dirent *namelist;int n = scandir(path.c_str(), 【 1】int i = 0;for(i ; i d_name;free(namelisti); 【 2】if(name != “.“ if(MAX_SCAN_FILE_NUM = fileNum )/MAX_SCAN_FILE_NUM=1000break;free(namelist); 【 3】return ;