事由:
公司中的其中一个设备管理程序用到了Socket通信,程序本身作为服务端,每当收到一条客户端发过来的消息时就先显示一下日志,很自然的采用了CListControl来显示,代码如下:
void WriteLog(CListCtrl& m_listLog, const CString& msg, int logLevel = LOG_LEVEL_NORMAL)
{
// ------------------------------------------
// 程序作者: 申志远 2012/08/16 11:22:53
// 函数功能: 将日志写入列表控件
// 参数说明:
// 注意事项:
// ------------------------------------------
int rowPos = m_listLog.GetItemCount();
if ( rowPos >= m_MaxWindowLine )
{
// 删除首行,rowPos为最后一个行。
m_listLog.DeleteItem(0);
rowPos -= 1;
}
// 插入新的日志信息
m_listLog.InsertItem(rowPos, GetFormatTime("%04d-%02d-%02d %02d:%02d:%02d:%03d").c_str() );
m_listLog.SetItemText(rowPos, 1, msg);
m_listLog.SetItemText(rowPos, 2, ( logLevel == LOG_LEVEL_NORMAL ? "正常": logLevel == LOG_LEVEL_WARNNING ? "警告":"错误" ) );
m_listLog.SetColumnWidth(1, LVSCW_AUTOSIZE );
m_listLog.EnsureVisible(rowPos, FALSE);
}
平时运行没有发现问题,但测试组的同事用LoadRunner来进行压力测试,每秒发送1000个XML文本过来,发现程序的内存在不断增长,直到内存不足而产生异常。
在网上找来找去问的人多,真正有效的解答却没有。
注意,这里已经排除了内存泄露的问题,因为没有进行任何的new 和 delete。
最后用google搜索外国网站,给出一个不错的答案:
其实CListControl占用的内存已经没用了,但是Windows没有立即释放,而是暂存在程序堆里,以便如果下次再用的时候可以立即提供而不必再申请。
只要我们在自己的程序中调用 SetProcessWorkSetSize即可清除进程不再用的内存。
void WriteLog(CListCtrl& m_listLog, const CString& msg, int logLevel = LOG_LEVEL_NORMAL)
{
// ------------------------------------------
// 程序作者: 申志远 2012/08/16 11:22:53
// 函数功能: 将日志写入列表控件
// 参数说明:
// 注意事项:
// ------------------------------------------
int rowPos = m_listLog.GetItemCount();
if ( rowPos >= m_MaxWindowLine )
{
// 删除首行,rowPos为最后一个行。
m_listLog.DeleteItem(0);
rowPos -= 1;
// 清除多余的内存
::SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1);
}
// 插入新的日志信息
m_listLog.InsertItem(rowPos, GetFormatTime("%04d-%02d-%02d %02d:%02d:%02d:%03d").c_str() );
m_listLog.SetItemText(rowPos, 1, msg);
m_listLog.SetItemText(rowPos, 2, ( logLevel == LOG_LEVEL_NORMAL ? "正常": logLevel == LOG_LEVEL_WARNNING ? "警告":"错误" ) );
m_listLog.SetColumnWidth(1, LVSCW_AUTOSIZE );
m_listLog.EnsureVisible(rowPos, FALSE);
}