C++ free()导致堆栈溢出

C++ free()导致堆栈溢出,c++,stack-overflow,C++,Stack Overflow,我正在尝试使用一些通信dll使用Visual Studio C++开发一个应用程序。 在其中一个DLL中,我有一个堆栈溢出异常 我有两个函数,一个接收数据包,另一个函数对数据包进行一些操作 static EEcpError RxMessage(unsigned char SrcAddr, unsigned char SrcPort, unsigned char DestAddr, unsigned char DestPort, unsigned char* pMessage, unsigned

我正在尝试使用一些通信
dll
使用Visual Studio C++开发一个应用程序。 在其中一个DLL中,我有一个堆栈溢出异常

我有两个函数,一个接收数据包,另一个函数对数据包进行一些操作

static EEcpError RxMessage(unsigned char SrcAddr, unsigned char SrcPort, unsigned char DestAddr, unsigned char DestPort, unsigned char* pMessage, unsigned long MessageLength)
{
    EEcpError Error = ERROR_MAX;
    TEcpChannel* Ch = NULL;
    TDevlinkMessage* RxMsg = NULL;

    // Check the packet is sent to an existing port
    if (DestPort < UC_ECP_CHANNEL_NB)
    {
        Ch = &tEcpChannel[DestPort];
        RxMsg = &Ch->tRxMsgFifo.tDevlinkMessage[Ch->tRxMsgFifo.ucWrIdx];

        // Check the packet is not empty
        if ((0UL != MessageLength)
            && (NULL != pMessage))
        {
            if (NULL == RxMsg->pucDataBuffer)
            {
                // Copy the packet
                RxMsg->SrcAddr = SrcAddr;
                RxMsg->SrcPort = SrcPort;
                RxMsg->DestAddr =DestAddr;
                RxMsg->DestPort = DestPort;
                RxMsg->ulDataBufferSize = MessageLength;
                RxMsg->pucDataBuffer = (unsigned char*)malloc(RxMsg->ulDataBufferSize);
                if (NULL != RxMsg->pucDataBuffer)
                {
                    memcpy(RxMsg->pucDataBuffer, pMessage, RxMsg->ulDataBufferSize);

                    // Prepare for next message
                    if ((UC_ECP_FIFO_DEPTH - 1) <= Ch->tRxMsgFifo.ucWrIdx)
                    {
                        Ch->tRxMsgFifo.ucWrIdx = 0U;
                    }
                    else
                    {
                        Ch->tRxMsgFifo.ucWrIdx += 1U;
                    }

                    // Synchronize the application
                    if (0 != OS_MbxPost(Ch->hEcpMbx))
                    {
                        Error = ERROR_NONE;
                    }
                    else
                    {
                        Error = ERROR_WINDOWS;
                    }
                }
                else
                {
                    Error = ERROR_WINDOWS;
                }
            }
            else
            {
                // That should never happen. In case it happens, that means the FIFO
                // is full. Either the FIFO size should be increased, or the listening thread 
                // does no more process the messages.
                // In that case, the last received message is lost (until the messages are processed, or forever...)
                Error = ERROR_FIFO_FULL;
            }
        }
        else
        {
            Error = ERROR_INVALID_PARAMETER;
        }
    }
    else
    {
        // Trash the packet, nothing else to do
        Error = ERROR_NONE;
    }

    return Error;
}

static EEcpError ProcessNextRxMsg(unsigned char Port, unsigned char* SrcAddr, unsigned char* SrcPort, unsigned char* DestAddr, unsigned char* Packet, unsigned long* PacketSize)
{
    EEcpError Error = ERROR_MAX;
    TEcpChannel* Ch = &tEcpChannel[Port];
    TDevlinkMessage* RxMsg = &Ch->tRxMsgFifo.tDevlinkMessage[Ch->tRxMsgFifo.ucRdIdx];

    if (NULL != RxMsg->pucDataBuffer)
    {
        *SrcAddr = RxMsg->ucSrcAddr;
        *SrcPort = RxMsg->ucSrcPort;
        *DestAddr = RxMsg->ucDestAddr;
        *PacketSize = RxMsg->ulDataBufferSize;
        memcpy(Packet, RxMsg->pucDataBuffer, RxMsg->ulDataBufferSize);

        // Cleanup the processed message
        free(RxMsg->pucDataBuffer);   // <= Exception stack overflow after 40 min
        RxMsg->pucDataBuffer = NULL;
        RxMsg->ulDataBufferSize = 0UL;
        RxMsg->ucSrcAddr = 0U;
        RxMsg->ucSrcPort = 0U;
        RxMsg->ucDestAddr = 0U;
        RxMsg->ucDestPort = 0U;

        // Prepare for next message
        if ((UC_ECP_FIFO_DEPTH - 1) <= Ch->tRxMsgFifo.ucRdIdx)
        {
            Ch->tRxMsgFifo.ucRdIdx = 0U;
        }
        else
        {
            Ch->tRxMsgFifo.ucRdIdx += 1U;
        }

        Error =ERROR_NONE;
    }
    else
    {
        Error = ERROR_NULL_POINTER;
    }

    return Error;
}
static EEcpError RxMessage(unsigned char srcadr、unsigned char SrcPort、unsigned char DestAddr、unsigned char DestPort、unsigned char*pMessage、unsigned long MessageLength)
{
EEcpError Error=错误_MAX;
TEcpChannel*Ch=NULL;
TDevlinkMessage*RxMsg=NULL;
//检查数据包是否发送到现有端口
如果(目的港tRxMsgFifo.tDevlinkMessage[Ch->tRxMsgFifo.ucWrIdx];
//检查数据包是否为空
如果((0UL!=消息长度)
&&(NULL!=pMessage))
{
如果(NULL==RxMsg->pucDataBuffer)
{
//复制数据包
RxMsg->srcadr=srcadr;
RxMsg->SrcPort=SrcPort;
RxMsg->DestAddr=DestAddr;
RxMsg->DestPort=DestPort;
RxMsg->ulDataBufferSize=MessageLength;
RxMsg->pucDataBuffer=(无符号字符*)malloc(RxMsg->ulDataBufferSize);
如果(NULL!=RxMsg->pucDataBuffer)
{
memcpy(RxMsg->pucDataBuffer、pMessage、RxMsg->ulDataBufferSize);
//为下一条消息做准备
if((UC_ECP_FIFO_深度-1)tRxMsgFifo.ucWrIdx)
{
Ch->tRxMsgFifo.ucWrIdx=0U;
}
其他的
{
Ch->tRxMsgFifo.ucWrIdx+=1U;
}
//同步应用程序
如果(0!=OS_MbxPost(Ch->hEcpMbx))
{
错误=错误\无;
}
其他的
{
错误=错误窗口;
}
}
其他的
{
错误=错误窗口;
}
}
其他的
{
//这是不应该发生的。万一发生了,那就意味着先进先出
//已满。应增加FIFO大小,或侦听线程
//不再处理消息。
//在这种情况下,最后收到的消息将丢失(直到消息被处理,或永远……)
错误=错误\先进先出\已满;
}
}
其他的
{
错误=错误\无效\参数;
}
}
其他的
{
//扔掉这个包,别无选择
错误=错误\无;
}
返回误差;
}
静态EEcpError ProcessNextRxMsg(无符号字符端口、无符号字符*SrcAddr、无符号字符*SrcPort、无符号字符*DestAddr、无符号字符*数据包、无符号长*数据包大小)
{
EEcpError Error=错误_MAX;
TEcpChannel*Ch=&TEcpChannel[端口];
TDevlinkMessage*RxMsg=&Ch->tRxMsgFifo.TDevlinkMessage[Ch->tRxMsgFifo.ucRdIdx];
如果(NULL!=RxMsg->pucDataBuffer)
{
*srcadr=RxMsg->ucsrcadr;
*SrcPort=RxMsg->ucSrcPort;
*DestAddr=RxMsg->ucDestAddr;
*PacketSize=RxMsg->ulDataBufferSize;
memcpy(数据包,RxMsg->pucDataBuffer,RxMsg->ulDataBufferSize);
//清除已处理的消息
free(RxMsg->pucDataBuffer);//pucDataBuffer=NULL;
RxMsg->ulDataBufferSize=0UL;
RxMsg->ucsrcadr=0U;
RxMsg->ucSrcPort=0U;
RxMsg->ucDestAddr=0U;
RxMsg->ucDestPort=0U;
//为下一条消息做准备
if((UC\u ECP\u FIFO\u DEPTH-1)tRxMsgFifo.ucRdIdx)
{
Ch->tRxMsgFifo.ucRdIdx=0U;
}
其他的
{
Ch->tRxMsgFifo.ucRdIdx+=1U;
}
错误=错误\无;
}
其他的
{
错误=错误\u空\u指针;
}
返回误差;
}
问题发生在40分钟后,在这段时间里我收到了很多数据包,一切都很顺利。 40分钟后,空闲服务器上发生堆栈溢出异常。 我不知道出了什么问题

有人能帮我吗

谢谢。

一些建议:

  • 线路

     memcpy(Packet, RxMsg->pucDataBuffer, RxMsg->ulDataBufferSize);
    
    有点可疑,因为它发生在崩溃的
    free()
    调用之前。如何分配
    数据包
    ,如何确保此处不会发生缓冲区溢出

  • 如果这是一个异步/多线程程序,您是否有必要的锁来防止同时写入/读取数据
  • 如果您仍然需要找到问题,最好的办法是运行Valgrind之类的工具,以帮助更精确地诊断和缩小内存问题。正如dasblinklight在评论中提到的,这个问题很可能起源于其他地方,只是碰巧出现在
    free()
    调用中

  • 这个问题很可能与
    free
    的特定调用无关-它发生的时间比这个更早。例如,如果覆盖正在释放的块的“簿记”信息,则可能会发生此问题。使用valgrind运行以查看实际内存错误。有关stackoverflow的问题应该在这里还是在meta上?@user93353哈哈哈,很好的一个(我希望)尝试一下,看看它是否发现了什么。谢谢您的回答。关于您的注释uesp,ProcessNextRxMsg函数在线程中的另一个DLL中调用。以下是数据包的分配方式:无符号字符数据包[US_ECP_MESSAGE_LENGTH_MAX];然后,在线程中的While循环中:memset(Packet,0,US_ECP_MESSAGE_LENGTH_MAX);//准备下一包。我注意到一些奇怪的事情:调用方DLL中创建时的数据包大小是20240,但当我检查第二个DLL中的数据包大小时(其中t