现象、问题描述
软件中的变量赋初值问题如果处理不当,将会在系统中引入随机值,这些随机值将会给产品带来难以定位和解决的缺陷,本文描述一种MEMCPY的错误使用带来的赋初值失败问题并给出正确的写法。
关键过程、根本原因分析
我们系统中有许多地方都需要对一个数组中的多个元素进行相同的初始化操作,笔者在代码中见到如下的写法,
if (maxGRPTupleNum>0)
{
mapCircuitSearchTable[0].groupNo = NULL_TKGROUP_NO;
mapCircuitSearchTable[0].from = NULL_CIRCUIT_NO;
mapCircuitSearchTable[0].end = NULL_CIRCUIT_NO;
mapCircuitSearchTable[0].masterEnd = NULL_CIRCUIT_NO;
mapCircuitSearchTable[0].freeNum = 0;
mapCircuitSearchTable[0].totalNum = 0;
mapCircuitSearchTable[0].reservedNum = 0;
memcpy(&mapCircuitSearchTable[1],&mapCircuitSearchTable[0],
sizeof(mapCircuitSearchTable[0])*(maxGRPTupleNum-1));
memcpy(mapCircuitPreoccupySearchTable,mapCircuitSearchTable,
sizeof(mapCircuitSearchTable[0])*maxGRPTupleNum);
}
请注意红色部分的代码:
memcpy(&mapCircuitSearchTable[1],&mapCircuitSearchTable[0],
sizeof(mapCircuitSearchTable[0])*(maxGRPTupleNum-1));
看上去好像没有什么问题,但是总觉得这样写不怎么可靠,到底这样写会出现什么结果呢?
我们先说明作者的本意,他的本意是希望把mapCircuitSearchTable[]这个数组中的所有元素都初始化成元素mapCircuitSearchTable[0]的值,因此,他希望MEMCPY能够这样执行:
先把元素0中的值拷贝到元素1中;
然后把元素1中的值拷贝到元素2中;
然后把元素2中的值拷贝到元素3中;
……
这样顺序执行,就能够实现他的目的。
但是,实际上这样写会出现什么情况呢?
MEMCPY(A,B,C)的作用是将从B地址开始的长度为C的地址拷贝到A开始长度为C的内存区域中,因此上面代码实际的执行结果更应该是这样:
把从元素0开始的各元素内容拷贝到从元素1开始的各元素内容中
结果就成了:元素0中内容拷贝到元素1中,元素1中拷贝到元素2中等等。
MEMCPY是内存的块拷贝,不是顺序执行元素拷贝
结论、解决方案及效果
建议将红色部分代码修改如下:
for (i = 1; i < maxGRPTupleNum; i++)
{
memcpy( &mapCircuitSearchTable[i], &mapCircuitSearchTable[0],
sizeof(mapCircuitSearchTable[0]) );
}
这样就完全可以保证代码执行的结果为代码作者的本意了。
经验总结、预防措施和规范建议
在代码编写过程中要严格界定操作系统提供的各个系统函数或者库函数的功能,不能主观臆断函数功能,尤其是在对数据赋初值的时候,如果赋初值出现问题,则可能会导致一些数据的初值为随机值,导致一些随机出现的问题出现,给产品质量带来难以定位和解决的隐患。
备注
无。
考核点
变量赋值
试题
如下说法,哪些是正确的(A B C)
A: 代码编写过程中要严格界定操作系统提供的各个系统函数或者库函数的功能,不能主观臆断函数功能
B: 变量赋初值的时候,要关注赋值的合法性和正确性,如果赋初值出现问题,则可能会导致一些变量的初值为随机值,导致一些随机出现的问题,给产品带来难以定位和解决的隐患
C: 使用变量前,一定要对变量进行赋值
D:只要申明变量,不用刻意关注变量是否初始化,是否合法,并且是否正确赋值
阅读(357) | 评论(0) | 转发(0) |