200910
来源:互联网 发布:数空车床编程视频教程 编辑:程序博客网 时间:2024/06/06 07:24
1 题目概述:采用动态单向链表实现内存监控功能
1.1 试题简介
使用动态单链表的方式,不考虑多线程,编写MLC(Memory Leak Check)程序,监控应用程序的内存申请释放动作。
请考生仔细阅读以下几个章节,注意题目要求和工程、工具的介绍。
答卷提交:如果采用VC调测环境(推荐使用VC环境),则把工程中的mlc目录(包括完成的源码跟测试代码)打包;如果采用Tornado调测环境(可以使用,需要考生参考试题中的用例进行测试),则把源文件mlc_main.c和mlc_main.h打包。打包文件的命名格式为“考试级别数字+调测环境代号+姓名的第一个字母+8位工号”的格式”,例如:
如李四的工号为00198765,考1级,使用VC调测环境(代号为VC),则打包文件的名称为:
1VC l00198765.rar
再如张三的工号为00187658,考0级,使用Tornado调测环境(代号为TO),则打包文件的名称为:0TO z00187658.rar
1.2 试题说明
注:本次考试提供统一的可编译可运行的调测平台,考生只需事前安装相应的开发工具即可。考试中如果考生选用VC调测(推荐使用),则直接使用提供的工程即可,Visual C++ 6.0安装会在考前知会到各个级别考生,开发环境:Visual C++ 6.0 ,测试环境:CPPUNIT;如果使用Tornado进行调测,则可参考试题中提供的“CExampleTest(测试参考).c”文件思路进行测试。
不考虑多线程,使用动态单链表的方式进行操作:在应用程序申请内存时,需要把该内存节点的信息插入链表进行记录;在应用程序释放内存时,把相应内存节点的信息从链表中删除;在应用程序退出时,如果链表中仍然存在节点,说明应用程序存在内存泄漏。应用程序不存在内存泄漏,则链表应该为空。
1.3 试题详细要求
1、MLC编程要求(一)
MLC程序需要完成以下标准接口,提供的框架中的源码是为了程序测试而进行的简单实现,请大家完成完备的功能(相关的类型定义会在考题提供的头文件中提供):
/*内存分配函数*/
void *MLC_MemAlloc(VOS_UINT32 ulPidSid, VOS_UINT8 ucPtNo, VOS_UINT32 ulSize, VOS_CHAR *pcFileName, VOS_UINT32 ulLine);
/*内存释放函数*/
VOS_VOID MLC_MemFree(VOS_UINT32 ulPidSid, VOS_VOID *pAddr);
/*内存泄漏检查函数*/
VOS_UINT32 MLC_CheckIfMemLeak (VOS_UINT32 *pulAddrNum, VOS_VOID* pAddrArray[]);
/*自动回收泄漏的内存*/
VOS_VOID MLC_CollectMemory(VOS_VOID);
附参数说明
ulPidSid 申请内存的模块ID ,MLC程序进行内存申请时,请统一使用VOS_PID_SYS
ucPtNo 已经创建了的内存分区号, MLC程序进行内存申请时,请统一使用DYNAMIC_DOPRA_MEM_PT
ulSize 要申请的内存的大小
2、MLC编程要求(二)
/*内存泄漏检查函数,如果发现内存泄漏则按照下面的格式进行打印,如果没有泄漏则打印没有泄漏的提示信息*/
VOS_UINT32 MLC_CheckIfMemLeak (VOS_UINT32 *pulAddrNum, VOS_VOID* pAddrArray[]);
打印格式要求如下(示例):
Memory Leak Found:
No. FileName Line MemAddr MemSize
1 comm_test.c 63 0x12345678 100
2 test1.c 10 0x11223377 20
说明:
输出参数:
ulAddrNum为泄漏的内存块数目
pAddrArray为存储泄漏的内存块地址的buff,系统提供的默认buff大小为2048,大家可以根据自己测试需要修改CExampleTest.cpp中如下变量中的2048为所需要的大小
VOS_VOID* g_pAddrArray[2048] = { 0 }; /*定义存放泄漏的内存块地址的buff*/
返回值 :VOS_OK没有泄漏/VOS_ERR存在泄漏
FileName,文件名,文件路径无需打印。
3、MLC编程要求(三)
系统框架包括一个.h一个.c
mlc_main.h 定义对外提供的标准接口
mlc_main.c 完成程序功能的源代码,考生的代码均应放在此文件中。
大家需要完成下图中的“MLC程序”,图中的“应用程序”是单独提供给大家的测试框架(直接集成在试题中的VC工程中),用来对完成的程序进行自测试,测试的粒度请大家根据进度做相应安排。如果采用Tornado调测环境,则可参考试题中提供的“CExampleTest(测试参考).c”文件思路进行测试。
应用程序使用MLC程序提供的标准对外接口进行内存操作,并且测试检查以及回收等功能,所以标准对外接口必须按照系统定义的提供,不允许修改。
1.4 代码的验收用例参考(提供部分用例,参见CExampleTest.cpp文件)
注:此处只提供基本的验收用例,考生应针对题目操作和底层软件开发常识考虑各种应用的异常情况。VC调测环境可以直接使用,如果使用Tornado调测环境,则考生可通过分析如下的测试代码了解基本测试用例的要求。
#include "mlc_main.h“
// 定义测试用的PID
#define PID_TEST_MLC 110
VOS_VOID* g_paMemLeakAddrArray[2048] = { 0 }; /*定义存放泄漏的内存块地址的buff*/
// 注册测试套到CppUnit
CPPUNIT_TEST_SUITE_REGISTRATION( ExampleTest );
测试用例(一)
用例1:申请释放正常用例检测,无内存泄漏上报。
// 测试用例实现示例
void ExampleTest::TestCase01()
{
VOS_UINT32 ulSize = 10;
VOS_UINT32 ulMemLeakNum = 0;
VOS_VOID* pAddr = VOS_NULL_PTR;
// 初始化Buf
VOS_MemSet(g_paMemLeakAddrArray, 0, sizeof(g_paMemLeakAddrArray));
// 申请内存
pAddr = MLC_MemAlloc(PID_TEST_MLC, DYNAMIC_MEM_PT, ulSize, __FILE__, __LINE__);
if (VOS_NULL_PTR != pAddr)
{
// 释放内存
MLC_MemFree(PID_TEST_MLC, pAddr);
}
// 检查结果
CPPUNIT_ASSERT(VOS_OK == MLC_CheckIfMemLeak(&ulMemLeakNum, g_paMemLeakAddrArray));
CPPUNIT_ASSERT(0 == ulMemLeakNum);
}
测试用例(二)
//用例2:泄漏1块内存,进行自动回收
void ExampleTest::TestCase02()
{
VOS_UINT32 ulSize = 10;
VOS_VOID* pAddr = VOS_NULL_PTR;
VOS_UINT32 ulMemLeakNum = 0;
VOS_VOID* pAddrArray[2048] = { 0 };
// 初始化Buf
VOS_MemSet(g_paMemLeakAddrArray, 0, sizeof(g_paMemLeakAddrArray));
// 申请内存
pAddr = MLC_MemAlloc(PID_TEST_MLC, DYNAMIC_MEM_PT, ulSize, __FILE__, __LINE__);
pAddrArray[0] = pAddr;
// 检查结果,因为MLC_CheckIfMemLeak是打桩的,故不通过,大家完成MLC_CheckIfMemLeak后应该为测试通过
CPPUNIT_ASSERT(VOS_ERR == MLC_CheckIfMemLeak(&ulMemLeakNum, g_paMemLeakAddrArray));
CPPUNIT_ASSERT(pAddrArray[0] == g_paMemLeakAddrArray [0]);
CPPUNIT_ASSERT(1 == ulMemLeakNum);
//回收泄漏的内存
MLC_CollectMemory();
// 检查结果
CPPUNIT_ASSERT(VOS_OK == MLC_CheckIfMemLeak(&ulMemLeakNum, g_paMemLeakAddrArray));
}
测试用例(三)
//用例3:泄漏多块内存,进行自动回收
// 一级考生自行添加测试用例实现
// void ExampleTest::TestCase03()
// {
//
// }
测试用例(四)
//用例4:释放一段没有申请的内存,应返回不能释放,链表没有变化;
// 一级考生自行添加测试用例实现
// void ExampleTest::TestCase04()
// {
//
// }
大家可以根据需要自行添加用例进行测试,在CExampleTest.cpp中增加用例函数,在CExampleTest.h中增加新增用例的申明
1.5 代码的验收标准
(1) 技能鉴定小组设计测试用例进行测试,不同用例分值可能不同;
(2) 0级满分:通过已提供1、2所有测试用例,且在规定时间内提交;
(3) 1级满分:除通过已提供1、2所有测试用例,还需考生自行思考其他测试用例,且在规定时间内提交;
1.6 系统库函数原型介绍
【一】使用VC调测环境
包含“vos.h”即可使用系统提供的库函数
内存申请:
VOS_VOID *VOS_MemAlloc( VOS_UINT32 ulPidSid, VOS_UINT8 ucPtNo, VOS_UINT32ulSize );
参数说明:
ulPidSid 申请内存的模块ID ,MLC程序进行内存申请时,请统一使用VOS_PID_SYS
ucPtNo 已经创建了的内存分区号, MLC程序进行内存申请时,请统一使用DYNAMIC_DOPRA_MEM_PT
ulSize 要申请的内存的大小
内存释放:
VOS_UINT32 VOS_MemFree( VOS_UINT32 ulPidSid, void *pAddr );
参数说明:
ulPidSid 申请内存的模块ID
pAddr 所要释放的内存块的首地址
打印函数:
VOS_INT32 vos_printf( VOS_CHAR *pscformat, ... );
Example:
vos_printf("%c\t%s\r\n",cVal,acVal);
【二】使用Tornado调测环境
内存申请:
void *malloc
(
size_t nBytes /* number of bytes to allocate */
)
void *memalign
(
unsigned alignment, /* boundary to align to (power of 2) */
unsigned size /* number of bytes to allocate */
)
内存释放:
void free
(
void * ptr /* pointer to block of memory to free */
)
打印函数:
int printf
(
const char * fmt, /* format string to write */
... /* optional arguments to format string */
)
Example:
printf(“[EXAM] Hello World \n”);
【三】MLC程序模板(以VC工程为例,具体参考试题提供的源文件)
#include "vos.h"
#include “mlc_main.h“
VOS_VOID *MLC_MemAlloc (VOS_UINT32 ulPidSid, VOS_UINT8 ucPtNo, VOS_UINT32 ulSize, VOS_CHAR *pcFileName, VOS_UINT32 ulLine)
{
/*在这里完成功能*/
}
VOS_VOID MLC_MemFree (VOS_UINT32 ulPidSid, VOS_VOID *pAddr)
{
/*在这里完成功能*/
}
VOS_UINT32 MLC_CheckIfMemLeak (VOS_UINT32 *pulAddrNum, VOS_VOID* pAddrArray[])
{
/*在这里完成功能*/
}
返回值 :VOS_OK没有泄漏/VOS_ERR存在泄漏
VOS_VOID MLC_CollectMemory(VOS_VOID)
{
/*在这里完成功能*/
}
1.7 mlc_workspace工程介绍
cppunit:
测试框架,主要包含了cppunit的头文件以及库文件;
dopra:
编程平台,包含了基本头文件、库文件;
工程路径:
..\mlc_workspace\mlc_workspace\mlc_workspace\dopra\target\project\win32
点击Dopra.dsw直接运行
mlc:
源代码以及测试代码目录,大家需要完成的文件全部存储到此目录下;
pc-lint:
代码静态检查,大家直接执行下面的lint.bat即可对代码进行检查;
1.8 附录:应用程序测试运行示例以及相关注意事项(VC调测环境)
【一】在VC环境下编译运行后,出现如下运行结果:
图示为Demo中2个用例的执行结果,用例2因为函数功能没有完成而执行失败,
大家完成完备的函数功能后,用例应该为执行通过。
Runs:执行的总用例数
Failures:失败的用例数,这里指断言不成立
Errors:程序异常,比如空指针,除0操作等异常
【二】友情提醒
请注意随时保存结果,以避免意外损失