探究realloc用法,realloc函数对同一个地址重复操作会返回NULL!

一、在程序设计中,某次意外操作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;

调试结果:

img

二、编写独立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;
              }
        }
}

调试结果:

img

关于realloc对同一个地址重复操作会出现返回NULL结果疑问,目前寻找资料未能找到合理解释,该种现象的原理?

img

谢谢你提供的思路@不会写代码的猴子 ,按照这个思路做了一些实验进一步验证了。你答案中说的这个数据发生前移,原地址指向的空间被释放,再次调用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次出错

img

2、步进值stepValue 设为 2,测试10次,结果都如下 9次以后 p地址改变,第10次出错

img

3、步进值stepValue设为 3 测试10次都 如下: 7次以后 p地址改变,第8次出错

img

4、 步进值stepValue 设为 4 或5 测试10次 结果如下: 5次以后 p地址改变,第6次出错

img

5、步进值stepValue 设为 6 或7 测试10次 结果如下: 4次以后 p地址改变,第5次出错

img

6、 步进值stepValue 设为 8~15, 测试10次 结果如下: 3次以后 p地址改变,第4次出错

img

7、步进值stepValue 设为 16~69, 测试10次 结果如下: 2次以后 p地址改变,第3次出错

img

结论:realloc 的 old_addr 误用以后出错原因是因为realloc所使用的p地址改变,此时指针p悬挂,即原来地址已经被系统回收放回到了堆上,p指针无效,再用这段空间就会发生问题。以上参考了博主@不会写代码的猴子 提供思路。