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

这篇博客讨论了在C++开发中遇到的内存管理问题,具体表现为堆栈信息被破坏,导致内存崩溃。作者在处理数据包时,由于忽视了内存空间的堆属性,导致在拷贝过程中发生了越界,从而破坏了堆栈。通过检查内存内容和堆信息,作者发现了问题所在,并提供了内存拷贝时需要注意的细节。博客着重强调了正确理解和处理堆内存的重要性,以及防止内存溢出和越界的策略。
摘要由CSDN通过智能技术生成

今天在开发中对数据包的格式进行了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信息:

查看szbuff中内容

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

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

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

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隨意的風

如果你觉得有帮助,期待你的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值