找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 6172|回复: 6

ACE 在Acceptor接受后, 退出时内存泄漏. 求助

[复制链接]
发表于 2011-1-4 22:52:43 | 显示全部楼层 |阅读模式
// DBServer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <DbgHelp.h>
#include "ACE\ACE.h"
#pragma comment(lib, "DbgHelp.lib")
#include "ace/Asynch_Acceptor.h"
#include "ace/Proactor.h"
#include "ace/WIN32_Proactor.h"
#ifndef SAFE_DELETE
#define SAFE_DELETE(x) if( (x) != NULL ) { delete (x); (x) = NULL; }
#endif

class ProConnectAcceptor : public ACE_Asynch_Acceptor<ACE_Service_Handler>
{
public:
        virtual ACE_Service_Handler*                make_handler (void)
        {
                //return new  My_Service_Handler();
                return 0;
        }
};

class CAceProactor : public ACE_Task<ACE_MT_SYNCH>
{
public:
        void                                Init(unsigned int nThreadCount)
        {
                m_u4ThreadCount = nThreadCount;
        }
        ACE_Proactor*                GetProactor();

        bool                                        Stop()
        {
                ACE_Proactor::instance()->proactor_end_event_loop();
                return true;
        }

        virtual int                                open(void *args = 0)
        {
                activate(THR_NEW_LWP | THR_BOUND | THR_JOINABLE, m_u4ThreadCount);
                return 0;
        }

        virtual int                                svc(void);
        unsigned int                                        m_u4ThreadCount;  //处理的线程总数
};

int CAceProactor::svc()
{
        ACE_Proactor::instance()->proactor_run_event_loop();
        return 0;
}

ACE_Proactor*  CAceProactor::GetProactor()
{
        return ACE_Proactor::instance();
}

class MyPServer : public ACE_Task<ACE_MT_SYNCH>
{
public:
        int                                        start_server(const char* szIp, UINT nPort, UINT nMaxConnectNum);
        virtual INT                        End();
private:
        void                                CleanUp();
        void                                stop_server();
        virtual int                        svc(void);

private:
        ProConnectAcceptor                        *m_Acceptor;
        CAceProactor                                *m_AceProactor;

};

int MyPServer::start_server(const char* szIp, UINT nPort, UINT nMaxConnectNum)
{
        int nRet=0;
        ACE_INET_Addr m_listenAddr;
        //Proactor & Acceptor
        m_AceProactor = new CAceProactor();
        m_AceProactor->Init(ACE_OS::num_processors() * 2);

        m_Acceptor = new ProConnectAcceptor();
        m_listenAddr.set(nPort,szIp);

        //start logger
        unsigned int nMark = 0;
        msg_queue()->high_water_mark(10000);
        msg_queue()->low_water_mark(10000);

        if(activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED , 1) != -1)
        {
                nRet = m_Acceptor->open(m_listenAddr, 0, 1,ACE_DEFAULT_ASYNCH_BACKLOG, 1, m_AceProactor->GetProactor());
                m_AceProactor->open();       
        }
        return nRet;
}
INT        MyPServer::End()
{
        m_Acceptor->cancel();               
        stop_server();
        wait();
        CleanUp();
        return 0;
}


void MyPServer::CleanUp()
{
        SAFE_DELETE(m_Acceptor);
        if (m_AceProactor)
        {
                m_AceProactor->Stop();
                m_AceProactor->wait();
                SAFE_DELETE(m_AceProactor);
        }
}


void MyPServer::stop_server(void)
{
        ACE_Message_Block* mb = NULL;
        mb = new ACE_Message_Block(0, ACE_Message_Block::MB_STOP);
        this->putq(mb);
}

int MyPServer::svc (void)
{
        ACE_Message_Block *mb=NULL;
        ACE_Time_Value xtime;
        int nCount=0;

        while(true)
        {
                xtime=ACE_OS::gettimeofday()+ACE_Time_Value(3, 0);
                nCount  = getq(mb,&xtime);

                if((nCount != -1) && (mb->msg_type()  ==  ACE_Message_Block::MB_STOP))
                {
                        delete mb;
                        break;
                }
        }       
        return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
        //检测内存泄漏
#if defined(WIN32) && defined(_DEBUG)
        int tmpDbgFlag;

        tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
        tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
        tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
        _CrtSetDbgFlag(tmpDbgFlag);               
#endif //WIN32 & _DEBUG
        ACE::init();

        MyPServer aa;
        aa.start_server("127.0.0.1", 5264, 3);
        ///!!!!!!!在这个用客户端连接一次, 退出的时候就报泄漏
        Sleep(10*1000);
        aa.End();
       

        ACE::fini();
        return 0;
}
////当服务器接受过连接后,退出时就会报内存泄漏, 请大家帮帮忙,查一查,谢谢!
 楼主| 发表于 2011-1-5 17:44:13 | 显示全部楼层
悲哀呀, 自己顶一下!
发表于 2011-1-6 08:52:52 | 显示全部楼层
帮顶一下,以前我也有这样的问题,原因是ACCEPTOR的析构器释放掉不该释放的东西,你看看是否你也有此问题。
发表于 2011-1-10 13:43:41 | 显示全部楼层
你可以使用Boundschecker看看,
发表于 2011-2-18 16:50:21 | 显示全部楼层
这种情况应该是连接句柄关闭异常。需要确认连接父类句柄也要关闭!
发表于 2011-3-6 00:41:02 | 显示全部楼层
基本功不扎实,问题在 MyPServer::End() -> m_Acceptor->cancel();   
该API只对当前投递的IO有效。没有终端连接时,Accept的投递和 CancelIO都在主线程执行,所以不会有任何问题。当终端连接上时,m_Acceptor会在IOCP 工作线程继续投递 acceptex; 接下来 在住线程调用CancelIO自然就没效了。
顺便说下,在Windows2008以上版本支持 CancelIOEx,这个可以支持任何线程投递的IO。 不过ACE 好像还没加入此API
 楼主| 发表于 2011-3-9 17:44:06 | 显示全部楼层
正如cgd0282 所说, 确实如此。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-11-22 01:50 , Processed in 0.015010 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表