今天在开发中对数据包的格式进行了gige header的封装,所以需要在网络接收到数据流后不再提出gige header信息了。直接进行数据包对象的构造和process流程。但是发现在内存copy的时候出现的堆被破坏的情况。

1、内存数据错乱

直接上图

//
//
void CGpMsgGigeReadRegAck::process(void *pInfo, void* pData)
{
    CHECK(pInfo);

    CGpNetUdpClient* pNet = (CGpNetUdpClient*)pInfo;
    CHECK(pNet);

    CGpDeviceManager* pDevMgr = dynamic_cast<CGpDeviceManager*>(deviceManager(pNet->getProcessId()));
    CHECK(pDevMgr);

    // 字节序转换
    NET_SWITCH_DWORD(m_pInfo->unRegisterValue);

    // 构造cmdInfo
    int nAddSize = 0;
    int nCmdType = DEV_MGR_CMD_ACT_NONE;
    void* pActInfo = NULL;

    // 成功
    if (m_pInfo->header.usStatus == ACK_SUCESS)
    {
        // sdk内部用到的命令,额外处理
        switch (m_pInfo->header.unAckId)
        {

            ...

            case COMMAND_RW_MULTI_REGISTERS_COMMAND:
            {
                // 填充命令和值的信息
                StuMultiCommandsInfo info;
                memset(&info, 0, sizeof(StuMultiCommandsInfo));
                safeMemCopy(info.szDeviceCode, GP_MAX_CODE, pNet->getNetCode(), GP_MAX_CODE);
                info.unStatus = ACK_STATUS_SUCESS;
                info.unCmdsId = m_pInfo->header.unAckId;

                // 第1~n个寄存器
                int nLength = GP_MIN(m_pInfo->header.usLen, GP_MAX_COMMAND * sizeof(INT32));
                /*
                * 注意:此处的m_pInfo是堆上的内存空间,需要偏移的时候+,堆属性向上增长
                *                  |                |
                *                长|                |
                *                生|                |
                *                上|    栈:高地址   |
                *                向|                |
                *                + |                |
                *                ^ |                |
                *                | |    堆:低地址   |
                *                  |                |
                *               p->|                |
                *                  |                |
                */
                memcpy(info.szValues, (void*)((char*)m_pInfo - _GIGE_GVCP_PACKET_HEADER_SIZE), nLength);            //m_pInfo 是在堆中申请的空间,注意此处使用的是想低地址空间延伸!!!
                info.unCount = nLength / sizeof(UINT32);
                for (UINT32 index = 1; index < info.unCount; ++index)
                {
                    NET_SWITCH_DWORD(info.szValues[index]);
                }

                StuCmdInfo* pCmdInfo = (StuCmdInfo*)malloc(sizeof(StuCmdInfo) + sizeof(StuMultiCommandsInfo));
                CHECK(pCmdInfo);
                pCmdInfo->nCmdType = DEV_MGR_CMD_ACT_READ_COMMANDS;
                memcpy(pCmdInfo->pData, (void*)&info, sizeof(StuMultiCommandsInfo));

                pDevMgr->pushCmdCache(pCmdInfo);

                LOGMSG("CGpMsgGigeReadRegAck::process is suc ack_id=[%u] nValue=[%u]", m_pInfo->header.unAckId, m_pInfo->unRegisterValue);
            }
            break;
            default:
            {
                LOGERROR("m_pInfo->header.ack_id is error. status=[%u] cmd=[%u] len=[%u] ack_id=[%u] nValue=[%u]", m_pInfo->header.usStatus, m_pInfo->header.usCmd, m_pInfo->header.usLen, m_pInfo->header.unAckId, m_pInfo->unRegisterValue);
                return;
            }
            break;
        }
    }

    // push cmd devMgr
    if (nAddSize > 0 && nCmdType > DEV_MGR_CMD_ACT_NONE && pActInfo)
    {
        StuCmdInfo* pCmdInfo = (StuCmdInfo*)malloc(sizeof(StuCmdInfo) + nAddSize);
        CHECK(pCmdInfo);
        pCmdInfo->nCmdType = nCmdType;
        memcpy(pCmdInfo->pData, (void*)pActInfo, nAddSize);

        pDevMgr->pushCmdCache(pCmdInfo);
    }
}

查看m_pInfo信息:

【genius_platform软件平台开发】第十点:记一次网络数据包处理修改引起的内存堆信息在执行copy的时候数据错乱和一次内存堆栈信息被破坏_内存空间

查看szbuff中内容

【genius_platform软件平台开发】第十点:记一次网络数据包处理修改引起的内存堆信息在执行copy的时候数据错乱和一次内存堆栈信息被破坏_地址空间_02

(void*)((char*)m_pInfo - 8)地址内容:

【genius_platform软件平台开发】第十点:记一次网络数据包处理修改引起的内存堆信息在执行copy的时候数据错乱和一次内存堆栈信息被破坏_函数返回值_03

当时没有注意m_pInfo是堆上的空间(把这个事情给忘记了 !!),一运行发现内存结果不对。

【genius_platform软件平台开发】第十点:记一次网络数据包处理修改引起的内存堆信息在执行copy的时候数据错乱和一次内存堆栈信息被破坏_地址空间_04

2、堆信息被破坏导致内存崩溃

【genius_platform软件平台开发】第十点:记一次网络数据包处理修改引起的内存堆信息在执行copy的时候数据错乱和一次内存堆栈信息被破坏_内存空间_05

因为内存copy越界导致堆栈信息被破坏,在函数返回值,栈SP内容已经被破坏,导致RET失败。

【genius_platform软件平台开发】第十点:记一次网络数据包处理修改引起的内存堆信息在执行copy的时候数据错乱和一次内存堆栈信息被破坏_内存空间_06

【genius_platform软件平台开发】第十点:记一次网络数据包处理修改引起的内存堆信息在执行copy的时候数据错乱和一次内存堆栈信息被破坏_函数返回值_07