一、表象
下面这段代码的for循环,不进入循环,断点检查list里边是有元素的。
FOR_EACHDATA_INLIST(&Cfg_GetPtzMng()->stPresetList, pstPresetNode, stIterator)
{
if(pstPresetNode->ucUseFlag == 0)
{
continue;
}
hArryObject = iTrd_Json_CreateObject();
iTrd_Json_AddItemToArray(hArry,hArryObject);
iTrd_Json_AddItemToObject(hArryObject,(_UC*)"PresetId",iTrd_Json_CreateStrWithNum(pstPresetNode->uiPresetId));
iTrd_Json_AddItemToObject(hArryObject,(_UC*)"Name",iTrd_Json_CreateString(pstPresetNode->aucName));
iTrd_Json_AddItemToObject(hArryObject,(_UC*)"PicID",iTrd_Json_CreateString(pstPresetNode->aucPicID));
hObject = iTrd_Json_CreateObject();
iTrd_Json_AddItemToObject(hArryObject,(_UC*)"Point",hObject);
iTrd_Json_AddItemToObject(hObject,(_UC*)"X",iTrd_Json_CreateStrWithNum(pstPresetNode->stPtzPreset.iX));
iTrd_Json_AddItemToObject(hObject,(_UC*)"Y",iTrd_Json_CreateStrWithNum(pstPresetNode->stPtzPreset.iY));
}
二、表因
stPresetList 和 pstPresetNode 无法匹配
三、排查
1、检查pstPresetNode和List的类型是否匹配?
经过检查ok
2、检查pstPresetNode和stPresetList 中Node所占内存是否一致
发现问题:
_INT Cfg_AddPresetPoint(_INT iCamId, _UI uiPresetId,_UC *pucName, ST_ZJ_PRESET_POINT *pstPoint)
{
ST_COS_LIST_ITERATOR stIterator;
ST_CFG_PRESET_NODE *pstPresetNode = COS_NULL;
ST_CFG_PRESET_NODE *pstFreeNode = COS_NULL;
FOR_EACHDATA_INLIST(&Cfg_GetPtzMng()->stPresetList, pstPresetNode, stIterator)
{
if(pstPresetNode->uiPresetId == uiPresetId)
{
break;
}
else if(pstPresetNode->ucUseFlag == 0)
{
pstFreeNode = pstPresetNode;
}
}
if(pstPresetNode == COS_NULL)
{
if(pstFreeNode == COS_NULL)
{
pstPresetNode = (ST_CFG_PRESET_NODE*)COS_MALLOCCLR(sizeof(ST_CFG_PRESET_NODE));
COS_LIST_ADDTAIL(&Cfg_GetPtzMng()->stPresetList, pstPresetNode);
}
else
{
pstPresetNode = pstFreeNode;
}
pstPresetNode->uiPresetId = uiPresetId;
}
COS_MEMCPY(&pstPresetNode->stPtzPreset, pstPoint, sizeof(ST_ZJ_PRESET_POINT));
COS_STRNCPY(pstPresetNode->aucName, pucName,128);
pstPresetNode->ucUseFlag = 1;
Cfg_GetItemSign()->ucSavePtz = 1;
return COS_OK;;
}
添加到list中的Node节点在初始化的时候发生越界。
即倒数第四行COS_STRNCPY(pstPresetNode->aucName, pucName,128)
Node结构体声明中变量aucName是32字节,此处发生越界,有的编译器会直接crash。但是我的编译器就没有,干!
四、最终原因
strncpy的越界行为使得当时添加到stPresetList中的Node越界了4个字节,所以和正常声明的pstPresetNode匹配失败。
五、参考
函数原型:char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
man解释:If the array pointed to by s2 is a string that is shorter than n bytes, null bytes shall be appended to the copy in the array pointed to by s1, until n bytes in all are written.
事实上s2往往不如n那么长,于是s1剩余部分会全填0。今天碰到的问题就是,s1的长度不如n,但是dest指向的n的长度全部被改写,于是内存被越界写了0,程序挂掉了