You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下Epoll服务器清理客户端端口信息时触发double free错误求助

排查epoll服务器中"double free or corruption (out)"错误

问题核心原因

你遇到的double free错误是重复释放同一个内存块导致的:

  • 在receiveDataFromSctp函数中,你连续调用了两次cleanHashEntry,传入的是同一个ConnectedCU_t指针:
    cleanHashEntry((ConnectedCU_t *) events->data.ptr, GlobalMap1);
    cleanHashEntry((ConnectedCU_t *) events->data.ptr, GlobalMap2);
    
  • 而cleanHashEntry函数的末尾会执行free(val),这就导致同一个ConnectedCU_t结构体被释放了两次,触发内存损坏错误。

另外,你的逻辑存在误区:GlobalMap1和GlobalMap2存储的是ConnectedCU_t的指针,不是独立的结构体副本。清理哈希表只需要移除对应的条目,不需要重复释放结构体本身——结构体的内存只需要释放一次。


修复方案

步骤1:修改cleanHashEntry,移除重复释放逻辑

把cleanHashEntry中的free(val)操作删掉,让它只负责清理哈希表条目:

void cleanHashEntry(ConnectedCU_t *val, Sctp_Map_t *m) 
{   
    if(val != nullptr)
    {
        char *dummy;
        auto port = (uint16_t) strtol(val->portNumber, &dummy, 10);
        char searchBuff[2048]{};

        snprintf(searchBuff, sizeof searchBuff, "host:%s:%d", val->hostName, port);       
        if(m->find(searchBuff))
        {            
            m->erase(searchBuff);
        }

        if(m->find(val->enodbName))
        {            
            m->erase(val->enodbName);
        }

        // 移除这里的free(val)操作
    }
}

步骤2:在receiveDataFromSctp中统一释放内存

调用两次cleanHashEntry清理完两个哈希表后,再一次性释放ConnectedCU_t结构体:

if (done) 
{
    mdclog_write(MDCLOG_INFO, "Closed connection - descriptor = %d", message.peerInfo->fileDescriptor);        
    pthread_mutex_lock(&thread_lock);
    if (fcntl(message.peerInfo->fileDescriptor, F_GETFD) != -1) {
        mdclog_write(MDCLOG_DEBUG, "Closing connection - descriptor = %d", message.peerInfo->fileDescriptor);
        close(message.peerInfo->fileDescriptor);
        // 先清理两个哈希表的条目
        cleanHashEntry((ConnectedCU_t *) events->data.ptr, GlobalMap1);
        cleanHashEntry((ConnectedCU_t *) events->data.ptr, GlobalMap2);
        // 仅释放一次结构体内存
        ConnectedCU_t *peer = (ConnectedCU_t *) events->data.ptr;
        if(peer) {
            free(peer);
            peer = nullptr;
        }
    }
    pthread_mutex_unlock(&thread_lock);
}

额外注意点

因为服务器使用多线程监听epoll,要确保同一个连接的关闭事件不会被多个线程并发处理。当前代码已经通过pthread_mutex_lock(&thread_lock)加锁,需确认thread_lock是全局唯一的,且所有操作哈希表、释放资源的路径都持有该锁,避免并发问题。

内容的提问来源于stack exchange,提问作者myquest9 sh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 04:17:34