一、在程序设计中,某次意外操作realloc操作同一个地址,造成了其返回NULL异常。
realloc传入的指针与pCommandTemp指针所赋值不一致,在第三次realloc时必出现异常,
重启10次,现象稳定。
for(StopActionChild=mxmlFindElement(AutoChild,tree,"command",NULL,NULL,MXML_DESCEND);
StopActionChild!=NULL;
StopActionChild=StopActionChild->next->next)
{
pCommandTemp = (CommandInfo_t *)realloc((m_ProcInfos + m_ProcInfoNum)->ProcStopActions,sizeof(CommandInfo_t)*(CommandNum+1));
if(!pCommandTemp)
{
LOG_ERR("[appAutoProcLoadConfig-->realloc] pCommandTemp realloc error.\n");
free(m_ProcInfos);
m_ProcInfos=NULL;
mxmlDelete(tree); /*删除xml文件句柄*/
fclose(fp); /*关闭文件*/
return -1;
}
(m_ProcInfos+m_ProcInfoNum)->JudgeParamInfos->StopCommands = pCommandTemp;
memcpy(((m_ProcInfos+m_ProcInfoNum)->JudgeParamInfos->StopCommands+CommandNum)->Name, mxmlElementGetAttr(StopActionChild,"name"),30);
memcpy(((m_ProcInfos+m_ProcInfoNum)->JudgeParamInfos->StopCommands+CommandNum)->Type, mxmlElementGetAttr(StopActionChild,"type"),30);
((m_ProcInfos+m_ProcInfoNum)->JudgeParamInfos->StopCommands+CommandNum)->Tab = atoi(mxmlElementGetAttr(StopActionChild,"tab"));
((m_ProcInfos+m_ProcInfoNum)->JudgeParamInfos->StopCommands+CommandNum)->Code = atoi(mxmlElementGetAttr(StopActionChild,"code"));
CommandNum++;/*停止动作计数递增*/
}
(m_ProcInfos+m_ProcInfoNum)->JudgeParamInfos->StopCmdNum = CommandNum;
调试结果:
二、编写独立realloc测试程序,首先malloc一个commad结构体,然后重复用commad地址realloc,会在第三个循环出现异常,重启10次,故障现象稳定。
void exam_01()
{
CommandInfo_t * pCommandTemp=NULL;
CommandInfo_t * command=(CommandInfo_t * )malloc(sizeof(CommandInfo_t *));
int i;
for(i=0;i<100;i++)
{
pCommandTemp=(CommandInfo_t *)realloc(command,sizeof(CommandInfo_t )*(i+1));
LOG_WARN("\n<>realloc test: < pCommandTemp:0x%x,m_ProcInfoNum:%d,CommandNum:%d>
\n",pCommandTemp,0,i);
if(!pCommandTemp)
{
LOG_ERR("pCommandTemp realloc error.\n");
return;
}
}
}
调试结果:
关于realloc对同一个地址重复操作会出现返回NULL结果疑问,目前寻找资料未能找到合理解释,该种现象的原理?
谢谢你提供的思路@不会写代码的猴子 ,按照这个思路做了一些实验进一步验证了。你答案中说的这个数据发生前移,原地址指向的空间被释放,再次调用realloc会使用这个悬挂指针。这个有相关官方文件支持吗,比如技术手册或者源码分析之类的。
根据@不会写代码的猴子 提供的思路开展如下参考实验,实验硬件基于龙芯1J系列芯片,VxWorks操作系统6.7:
一、测试代码
int my_realloc_test(int stepValue)
{
char *p, *q;
int i;
p = (char*)malloc(1);
q = p;
printf("\r\n<-- my_realloc_test, stepValue: %d -->\r\n", stepValue);
printf("start p_addr: 0x%X, q_addr: 0x%X\r\n", p, q);
for(i=0; i<100; i++){
q = (char*)realloc(p, 1+i*stepValue);
printf("index: %d, p_addr: 0x%X, q_addr: 0x%X\n", i, p, q);
if(q==NULL){
printf("realloc error\n");
return -1;
}
}
printf("test Success!\n");
return 0;
}
void my_realloc_test_array(void)
{
int i, j;
for(i=1; i<70; i++){
for(j=0; j<10; j++){
my_realloc_test(i);
taskDelay(10);
}
printf("--------------------\r\n\r\n");
taskDelay(30);
}
}
二、实验数据
1、步进值stepValue 为1时。 测试10次 结果都如下: 17次以后 p地址改变,第18次出错
2、步进值stepValue 设为 2,测试10次,结果都如下 9次以后 p地址改变,第10次出错
3、步进值stepValue设为 3 测试10次都 如下: 7次以后 p地址改变,第8次出错
4、 步进值stepValue 设为 4 或5 测试10次 结果如下: 5次以后 p地址改变,第6次出错
5、步进值stepValue 设为 6 或7 测试10次 结果如下: 4次以后 p地址改变,第5次出错
6、 步进值stepValue 设为 8~15, 测试10次 结果如下: 3次以后 p地址改变,第4次出错
7、步进值stepValue 设为 16~69, 测试10次 结果如下: 2次以后 p地址改变,第3次出错
结论:realloc 的 old_addr 误用以后出错原因是因为realloc所使用的p地址改变,此时指针p悬挂,即原来地址已经被系统回收放回到了堆上,p指针无效,再用这段空间就会发生问题。以上参考了博主@不会写代码的猴子 提供思路。