服务器程序长时间运行,物理内存变化在60M左右,而虚拟内存缓慢增长。why?

时间:2021-11-24 20:11:38
写的一个服务器程序,物理内存保持在60M左右变化,而虚拟内存缓慢增长,运行几天之后已经增长到200多M。
内存泄露的可能性不大,不知道是不是new,delete太频繁导致的。
还有哪些情况会导致虚拟内存缓慢增长的?

请各位帮忙分析一下

24 个解决方案

#1


不是内存泄漏的可能性不大~~~

#2


写的一个服务器程序,物理内存保持在60M左右变化,而虚拟内存缓慢增长,运行几天之后已经增长到200多M。 
内存泄露的可能性不大,不知道是不是new,delete太频繁导致的。 
还有哪些情况会导致虚拟内存缓慢增长的? 

---------
你怎么知道不是内存泄露?

#3


运行的程序在任务管理中有两个显示内存的状态:内存使用和虚拟内存大小。
若是内存泄露,内存使用的值应该一直在增长,不会保持恒定

#4


1 可能正常
2 内存泄漏
3 SetProcessWorkingSetSize 

#5


来学习的~!

#6


自己做了个测试程序,频繁new, delete一块大内存,虚拟内存基本不变,所以我认为上面的问题应该不是内存碎片的导致的。

为了解决跑了几天的服务器程序,为啥虚拟内存会缓慢增长,6天之后达到300M的问题,最后才发现是内存泄露。
问题出在ACE_Asynch_Acceptor 监听器上,当有一个连接时,虚拟内存不变;当有多个连接进行断开然后再重连,
虚拟内存会按4K的步调缓慢递增。

这应该是ACE库造成的内存泄露,不知道哪位能帮忙解决一下。

#7


有没有可能是HANDLER没有释放掉呢?

#8


在写失败的时候会在回调函数中调用
ACE_OS::close(this->handle());

我在具体说一下我遇到的问题

ACE_Asynch_Acceptor 内存泄露

开发平台Windows,  vc2005
开发的一个服务器程序,运行几天后,虚拟内存由60M增长到200多M,并且还有缓慢增长的趋势。

后来经过不断测试,发现问题应该出现在ACE_Asynch_Acceptor监听器这个地方。
ACE_Asynch_Acceptor<MyClass>  listen;
if (0 != listen.open (p2p_listen_addr, 0, 0, 5, 1, 0, 1))
{
        ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("listen open failed.\n")));
}

测试内存泄露症状:
当有一个连接时,反复断开连接,不会出现内存泄露。
若有多个连接,断开连接若干次后,会出现内存泄露,以4K的步调缓慢增长。

#9


看你的补充,我还是觉得问题可能还是出在对handler对象的生命期管理上。

#10


顺便补充一下,在读写失败的时候都会关闭handle,断开连接。

我的分析如下:
当有新的连接到来,监听器会new一个新的MyClass对象,断开连接后,这个对象ace好像没有回收。
我尝试在读写失败时,关闭连接,然后delete this.
可惜没有达到目的,这个MyClass对象是delete掉了,但是却关闭了监听器的监听功能,不处理handle_accept
再也不能响应其他连接了

#11


晕,原因你认为handler是ACE_HANDLE啊。
这个MyClass应该就是你从ACE_Event_Hander或ACE_Svc_Handler继承的子类。。。
你不仅要关闭句柄,你可能是
重写了handle_close而没有调用destroy() //ACE_Svc_Handler的情况

重写close()并调用destroy();   //ACE_Svc_Handler的情况destroy会delete this;

#12


上面说对你的问题可能不适用。
我再看看ACE_Service_Handler的情况。。。。

#13


我看了一下Proactor_Test
你还是要自已管理ACE_Service_Handler的生命期。

#14


我管理ACE_Service_Handler的生命期是改写回调函数handle_read_stream_,handle_write_stream
在读写失败时候用ACE_OS::close(this->handle());
这个时候ACE应该回收该服务。
当有下个连接到来时,ACE再new一个新的服务。


#15


你应该delete this;

#16


对ACE不太了解.如果这种问题比较棘手的话,可以向ACE开发小组反映.
另外一个解决方案是.
做一个监护进程,每天夜里重新启动一下你的服务.

good luck

#17


若用delete this, 监听器不起作用了,再有新的连接到来,ace不会处理该连接,即不会new 一个新的服务对象进行处理。

我做了一个测试,在MyClass加入一个大的数组,当反复进行连接断开后,虚拟内存就基本上以这个数组的大小进行递增。
这应该可以反映出ACE_OS::close(this->handle())后,该MyClass对象没进行回收。

#18


你的MyClass是什么东西?

#19


我把MyClass精简一下,贴出来。
class MyClass : public ACE_Service_Handler
{
public:
    MyClass();
    ~MyClass();
    virtual void open (ACE_HANDLE h, ACE_Message_Block& mb);
    virtual int timeout();
protected:
    virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
    virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
    virtual int cancel ();
private:
    ACE_Message_Block* mb_read_;   // message block as read buffer
    ACE_Asynch_Read_Stream reader_;
    ACE_Asynch_Write_Stream writer_;
    ACE_UINT32 block_array_to_push[10240];   //测试用的大数组
}

在open函数中,会从内存池拿出一个消息块给mb_read_
当读写失败会调用ACE_OS::close(this->handle()),然后把mb_read_放回内存池

#20


关键在于handle_read_stream 和 handle_write_stream 及open对失败的处理有没有delete this
或者如果你管理MyClass池。
据我的观察,你光close套接字ACE_OS::close(this->handle())并不能达到释放Handler的作用。

#21


我在open失败,以及读写失败会执行下面方法
   
// cancel all operations
reader_.cancel();
writer_.cancel();

// close the socket
ACE_OS::shutdown(this->handle(),SD_BOTH);
ACE_OS::closesocket(this->handle());
this->handle(ACE_INVALID_HANDLE);

//若再加上下面代码,会出现关闭所有连接,并且ACE_Asynch_Acceptor <MyClass>  listen;该监听器不会监听新
//的连接,不能相应新的连接请求。(我的目的:就是要在这个地方让ACE回收该对象,或者直接把它delete掉。但是直接
//delete this 会出现问题)
delete this;

#22


经过我的测试,delete this不存在你的问题,并且内存也不要增加。

#23


delete this 后 ,监听器能继续工作,相应新的连接吗

#24


问题已经解决了,哈哈,谢谢各位。尤其感谢hhyttppd 

ACE不会回收MyClass对象,必须关闭socket句柄后delete this该对象。
delete this会引起异常的问题是由于其他地方正在读写该对象,导致异常。

#1


不是内存泄漏的可能性不大~~~

#2


写的一个服务器程序,物理内存保持在60M左右变化,而虚拟内存缓慢增长,运行几天之后已经增长到200多M。 
内存泄露的可能性不大,不知道是不是new,delete太频繁导致的。 
还有哪些情况会导致虚拟内存缓慢增长的? 

---------
你怎么知道不是内存泄露?

#3


运行的程序在任务管理中有两个显示内存的状态:内存使用和虚拟内存大小。
若是内存泄露,内存使用的值应该一直在增长,不会保持恒定

#4


1 可能正常
2 内存泄漏
3 SetProcessWorkingSetSize 

#5


来学习的~!

#6


自己做了个测试程序,频繁new, delete一块大内存,虚拟内存基本不变,所以我认为上面的问题应该不是内存碎片的导致的。

为了解决跑了几天的服务器程序,为啥虚拟内存会缓慢增长,6天之后达到300M的问题,最后才发现是内存泄露。
问题出在ACE_Asynch_Acceptor 监听器上,当有一个连接时,虚拟内存不变;当有多个连接进行断开然后再重连,
虚拟内存会按4K的步调缓慢递增。

这应该是ACE库造成的内存泄露,不知道哪位能帮忙解决一下。

#7


有没有可能是HANDLER没有释放掉呢?

#8


在写失败的时候会在回调函数中调用
ACE_OS::close(this->handle());

我在具体说一下我遇到的问题

ACE_Asynch_Acceptor 内存泄露

开发平台Windows,  vc2005
开发的一个服务器程序,运行几天后,虚拟内存由60M增长到200多M,并且还有缓慢增长的趋势。

后来经过不断测试,发现问题应该出现在ACE_Asynch_Acceptor监听器这个地方。
ACE_Asynch_Acceptor<MyClass>  listen;
if (0 != listen.open (p2p_listen_addr, 0, 0, 5, 1, 0, 1))
{
        ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("listen open failed.\n")));
}

测试内存泄露症状:
当有一个连接时,反复断开连接,不会出现内存泄露。
若有多个连接,断开连接若干次后,会出现内存泄露,以4K的步调缓慢增长。

#9


看你的补充,我还是觉得问题可能还是出在对handler对象的生命期管理上。

#10


顺便补充一下,在读写失败的时候都会关闭handle,断开连接。

我的分析如下:
当有新的连接到来,监听器会new一个新的MyClass对象,断开连接后,这个对象ace好像没有回收。
我尝试在读写失败时,关闭连接,然后delete this.
可惜没有达到目的,这个MyClass对象是delete掉了,但是却关闭了监听器的监听功能,不处理handle_accept
再也不能响应其他连接了

#11


晕,原因你认为handler是ACE_HANDLE啊。
这个MyClass应该就是你从ACE_Event_Hander或ACE_Svc_Handler继承的子类。。。
你不仅要关闭句柄,你可能是
重写了handle_close而没有调用destroy() //ACE_Svc_Handler的情况

重写close()并调用destroy();   //ACE_Svc_Handler的情况destroy会delete this;

#12


上面说对你的问题可能不适用。
我再看看ACE_Service_Handler的情况。。。。

#13


我看了一下Proactor_Test
你还是要自已管理ACE_Service_Handler的生命期。

#14


我管理ACE_Service_Handler的生命期是改写回调函数handle_read_stream_,handle_write_stream
在读写失败时候用ACE_OS::close(this->handle());
这个时候ACE应该回收该服务。
当有下个连接到来时,ACE再new一个新的服务。


#15


你应该delete this;

#16


对ACE不太了解.如果这种问题比较棘手的话,可以向ACE开发小组反映.
另外一个解决方案是.
做一个监护进程,每天夜里重新启动一下你的服务.

good luck

#17


若用delete this, 监听器不起作用了,再有新的连接到来,ace不会处理该连接,即不会new 一个新的服务对象进行处理。

我做了一个测试,在MyClass加入一个大的数组,当反复进行连接断开后,虚拟内存就基本上以这个数组的大小进行递增。
这应该可以反映出ACE_OS::close(this->handle())后,该MyClass对象没进行回收。

#18


你的MyClass是什么东西?

#19


我把MyClass精简一下,贴出来。
class MyClass : public ACE_Service_Handler
{
public:
    MyClass();
    ~MyClass();
    virtual void open (ACE_HANDLE h, ACE_Message_Block& mb);
    virtual int timeout();
protected:
    virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
    virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
    virtual int cancel ();
private:
    ACE_Message_Block* mb_read_;   // message block as read buffer
    ACE_Asynch_Read_Stream reader_;
    ACE_Asynch_Write_Stream writer_;
    ACE_UINT32 block_array_to_push[10240];   //测试用的大数组
}

在open函数中,会从内存池拿出一个消息块给mb_read_
当读写失败会调用ACE_OS::close(this->handle()),然后把mb_read_放回内存池

#20


关键在于handle_read_stream 和 handle_write_stream 及open对失败的处理有没有delete this
或者如果你管理MyClass池。
据我的观察,你光close套接字ACE_OS::close(this->handle())并不能达到释放Handler的作用。

#21


我在open失败,以及读写失败会执行下面方法
   
// cancel all operations
reader_.cancel();
writer_.cancel();

// close the socket
ACE_OS::shutdown(this->handle(),SD_BOTH);
ACE_OS::closesocket(this->handle());
this->handle(ACE_INVALID_HANDLE);

//若再加上下面代码,会出现关闭所有连接,并且ACE_Asynch_Acceptor <MyClass>  listen;该监听器不会监听新
//的连接,不能相应新的连接请求。(我的目的:就是要在这个地方让ACE回收该对象,或者直接把它delete掉。但是直接
//delete this 会出现问题)
delete this;

#22


经过我的测试,delete this不存在你的问题,并且内存也不要增加。

#23


delete this 后 ,监听器能继续工作,相应新的连接吗

#24


问题已经解决了,哈哈,谢谢各位。尤其感谢hhyttppd 

ACE不会回收MyClass对象,必须关闭socket句柄后delete this该对象。
delete this会引起异常的问题是由于其他地方正在读写该对象,导致异常。