burstas / spserver

Automatically exported from code.google.com/p/spserver
Other
0 stars 1 forks source link

内存泄露 #14

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. 在主线程中创建Sp_httpServer
2. 在子线程中启动
3. 在主线程中启动,等待子线程关闭退出,删除Sp_httpServer
出现内存泄露,应该是 httpResponse 未清楚

code:
DWORD  WINAPI StartServer(LPVOID para)
{
    SP_IocpServer* pServer = (SP_IocpServer*)para;
    pServer->run();
    while (pServer->isRunning())
    {
        Sleep(1000);
    }
    return 0;
}

void CHostListView::OnStartlisten() 
{
    int port = 80, maxThreads = 50;
    const char * serverType = "hahs";

    if( 0 != sp_initsock() ) ASSERT( 0 );
    m_pIocpServer = 
        new SP_IocpServer( "", port, new SP_HttpHandlerAdapterFactory( new
CHttpServerHandlerFactory(this->m_hWnd) ) );
    m_pIocpServer->setTimeout( 60 );
    m_pIocpServer->setMaxThreads( maxThreads );
    m_pIocpServer->setReqQueueSize( 100, "HTTP/1.1 500 Sorry, server is busy
now!\r\n" );
    DWORD dwThreadId1;
    m_hStartServerThread = CreateThread( NULL, 0, StartServer,
(LPVOID)(m_pIocpServer), 0, &dwThreadId1 );
    sp_closelog();
}
关闭退出
    if (m_pIocpServer)
    {
        if (m_pIocpServer->isRunning())
        {
            m_pIocpServer->shutdown();
        }
        WaitForSingleObject(m_hStartServerThread,INFINITE);
        delete m_pIocpServer;
    }
What is the expected output? What do you see instead?

内存泄露
What version of the product are you using? On what operating system?

spserver-0.9.2
Please provide any additional information below.

谢谢

Original issue reported on code.google.com by zl110...@163.com on 18 Feb 2009 at 3:29

GoogleCodeExporter commented 9 years ago
在控制台程序中没有内存泄露,而再MFC下则存在内存泄露

Original comment by zl110...@163.com on 20 Feb 2009 at 12:38

GoogleCodeExporter commented 9 years ago
SP_IocpServer 
在退出的时候,对于部分的内存资源的确是没有进行释放的��
�在上面提到的案例
中,在 delete m_pIocpServer 
之后,程序还会继续运行吗?如果程序持续运行,并且不断��
�重
复上面的过程,那么会导致内存空间被耗尽。但是如果程序��
�着就退出了,那么并不是一个大问
题。程序退出之后,所占用的内存有 os 回收。

Original comment by stephen....@gmail.com on 22 Feb 2009 at 2:34

GoogleCodeExporter commented 9 years ago
非常感谢您的回答,在delete m_pIocpServer 
之后,程序就退出了。debug版本运行结束后vc提
示内存泄露。用bounderchecker检测也有泄露。查看泄露的内容主
要是SP_Response的header,如下:
int SP_HttpHandlerAdapter :: handle( SP_Request * request, SP_Response * 
response )
{
    SP_HttpRequestDecoder * decoder = ( SP_HttpRequestDecoder * ) request->getMsgDecoder();
    SP_HttpRequest * httpRequest = ( SP_HttpRequest * ) decoder->getMsg();

    httpRequest->setClinetIP( request->getClientIP() );

    SP_HttpResponse * httpResponse = new SP_HttpResponse();//此处new的内容并不是每次都释放,
在SP_HttpResponse的构造和析构函数处设置断点,程序开始后只��
�用一次析构函数,以后就只调
用构造函数,未见调用析构函数,导致程序每次响应新的请求�
��存都会增加。

Original comment by zl110...@163.com on 26 Feb 2009 at 6:25

GoogleCodeExporter commented 9 years ago

int SP_HttpHandlerAdapter :: handle( SP_Request * request, SP_Response * 
response )

在这个函数的最后,会有对 httpResponse 的处理。
如果 response 有 body 的部分,会把 httpRespnose 托管给 
SP_HttpResponseMsgBlock 。
如果没有 body 部分,直接 delete 。

223     if( NULL != httpResponse->getContent() ) {
224         response->getReply()->getFollowBlockList()->append(
225                 new SP_HttpResponseMsgBlock( httpResponse ) );
226     } else {
227         delete httpResponse;
228     }

SP_HttpResponseMsgBlock 会在释放的时候,delete reponse 。

101 SP_HttpResponseMsgBlock :: ~SP_HttpResponseMsgBlock()
102 {
103     if( NULL != mResponse ) delete mResponse;
104     mResponse = NULL;
105 }

发生泄漏的情况,只有在停止 SP_IocpServer 的时候才会发生。
在正常的处理流程下,按上面的逻辑处理,不会发生泄漏。

Original comment by stephen....@gmail.com on 26 Feb 2009 at 7:24

GoogleCodeExporter commented 9 years ago
Issue 13 has been merged into this issue.

Original comment by stephen....@gmail.com on 26 Feb 2009 at 7:25

GoogleCodeExporter commented 9 years ago
再次感谢您的回答,我发现在我下载的代码(SPSERVER-0.9.3)里
没有else部分
(line:226,227,228),所以导致了http头的内存泄露。加上上
述部分应该不会有错误了。
223     if( NULL != httpResponse->getContent() ) {
224         response->getReply()->getFollowBlockList()->append(
225                 new SP_HttpResponseMsgBlock( httpResponse ) );
226     } else {
227         delete httpResponse;
228     }

Original comment by zl110...@163.com on 26 Feb 2009 at 3:50

GoogleCodeExporter commented 9 years ago
我想起来了,这个 bug 是在 0.9.3 发布了之后才 fix 的,现在 
svn 上最新的代码是没有问题
的。但是 0.9.3 还是有问题的。

Original comment by liusi...@gmail.com on 27 Feb 2009 at 2:55

GoogleCodeExporter commented 9 years ago
你好,请教一个问题,svn的路径http://spserver.googlecode.com/svn/tru
nk/spserver-read-
only正确吗?我用tortoise下载提示找不到路径。
谢谢!!

Original comment by zl110...@163.com on 27 Feb 2009 at 5:12

GoogleCodeExporter commented 9 years ago
是 http://spserver.googlecode.com/svn/trunk/ ,后面的 spserver-read-only 
不是连在一起的。

Original comment by liusi...@gmail.com on 27 Feb 2009 at 5:16

GoogleCodeExporter commented 9 years ago
非常感谢,没有后面的spserver-read-only,呵呵,可以下载了。
在0.9.3的基础上修改后没有了http头的内存泄露,但是还有其��
�的一些内存泄露,下载完最新的
版本又试了一下,还是有内存泄露。不过这次好像是request的�
��存泄露,我看到很多泄漏的内存
是我请求服务器的url(运行sphttpserver的服务器的URL)。

Original comment by zl110...@163.com on 27 Feb 2009 at 6:52

GoogleCodeExporter commented 9 years ago
发现两处内存泄露
一处是请求头mURL
SP_HttpRequest :: ~SP_HttpRequest()
{
    if( NULL != mURI ) free( mURI );
    if (NULL != mURI )
    {
        free(mURL);
        mURL = NULL;
    }
另一处是:
SP_IocpEventArg :: ~SP_IocpEventArg()
{
    if( NULL != mInputResultQueue ) delete mInputResultQueue;
    mInputResultQueue = NULL;

    if( NULL != mOutputResultQueue ) delete mOutputResultQueue;
    mOutputResultQueue = NULL;

    if( NULL != mEventHeap ) delete mEventHeap;
    mEventHeap = NULL;

    if( NULL != mResponseQueue ) delete mResponseQueue;
    mResponseQueue = NULL;
//释放SessionManager
    if( NULL != mSessionManager ) delete mSessionManager;
    mSessionManager = NULL;

}

Original comment by zl110...@163.com on 27 Feb 2009 at 2:59

GoogleCodeExporter commented 9 years ago
多谢指出泄漏的地方,已经修改 checkin 到 svn 了。

Original comment by stephen....@gmail.com on 4 Mar 2009 at 6:26

GoogleCodeExporter commented 9 years ago
我第一次使用,用的 0.9.4 
版本,使用testiocpchat时,如果不使用runForever(), 而使用
run(),就会出现 内存泄露。代码如下:

int port = 5555;

    SP_OnlineSidList onlineSidList;

    //SP_IocpServer server( "", port, new SP_ChatHandlerFactory( &onlineSidList ) );

    // 网络服务器
    SP_IocpServer *m_pServer;

void CMainFrame::OnServiceStart()
{
    // TODO: 在此添加命令处理程序代码

    int maxThreads = 10;

    if( 0 != sp_initsock() ) assert( 0 );

    //SP_OnlineSidList onlineSidList;

    //SP_IocpServer server( "", port, new SP_ChatHandlerFactory( &onlineSidList ) );

    m_pServer = new SP_IocpServer( "", port, new SP_ChatHandlerFactory( &onlineSidList ) );
    m_pServer->setTimeout( 60 );
    m_pServer->setMaxThreads( maxThreads );
    m_pServer->setReqQueueSize( 100, "Sorry, server is busy now!\n" );

    //server.runForever();
    m_pServer->run ();

    sp_closelog();
} 

void CMainFrame::OnUpdateServiceStart(CCmdUI *pCmdUI)
{
    // TODO: 在此添加命令更新用户界面处理程序代码
}

void CMainFrame::OnServiceStop()
{
    // TODO: 在此添加命令处理程序代码

    if ( m_pServer )
    {
        if ( m_pServer->isRunning() )
            m_pServer->shutdown();

        delete m_pServer ;
    }

    m_pServer = NULL;
}

void CMainFrame::OnUpdateServiceStop(CCmdUI *pCmdUI)
{
    // TODO: 在此添加命令更新用户界面处理程序代码
}

Original comment by ollye...@126.com on 10 Dec 2009 at 2:07

GoogleCodeExporter commented 9 years ago
暂时先从 svn 拿最新的代码吧,之前发现的 memory leak 
问题都已经在最新的代码中解决了。
周末把最新的代码打包发布一个版本。

Original comment by stephen....@gmail.com on 11 Dec 2009 at 2:10

GoogleCodeExporter commented 9 years ago

Original comment by stephen....@gmail.com on 19 Mar 2011 at 4:05