https://blog.csdn.net/zhoukai216/article/details/89403363
最近在使用std::queue的時候,遇到一些奇怪的問題。我們使用std::queue來存放一些臨時的緩衝數據,然後有一個線程不斷地從queue裏取數據,寫入到文件中,之後會調用pop()函數將數據彈出。但是很奇怪的地在彈出的過程中,程序的內存佔用絲毫沒有減少。查了一些資料後發現,貌似std::queue底層自己有一套內存管理機制,只有在程序退出或是queue被銷燬的時候纔會釋放這一部分內存。筆者使用的測試代碼如下:
-
#include <stdio.h>
-
#include <queue>
-
#include <WinSock2.h>
-
template<typename Data>
-
class concurrent_queue
-
{
-
private:
-
std::queue<Data> the_queue;
-
public:
-
void push( const Data& data )
-
{
-
the_queue.push( data );
-
}
-
bool empty( ) const
-
{
-
return the_queue.empty( );
-
}
-
Data& front( )
-
{
-
return the_queue.front( );
-
}
-
Data const& front( ) const
-
{
-
return the_queue.front( );
-
}
-
void pop( )
-
{
-
the_queue.pop( );
-
}
-
int size( )
-
{
-
return the_queue.size( );
-
}
-
};
-
typedef struct FRAME
-
{
-
unsigned char* sPbuf;
-
int iSize;
-
};
-
int main() {
-
concurrent_queue<FRAME> frame_list;
-
FRAME f;
-
// push
-
for (int i = 0; i < 100000; i ++ ) {
-
FRAME f;
-
f.sPbuf = NULL;
-
f.sPbuf = new byte[ 1000 ];
-
f.iSize = 1000;
-
frame_list.push( f );
-
}
-
// pop
-
for (int i = 0; i < 100000; i ++ ) {
-
FRAME f2 = frame_list.front( );
-
delete [] f2.sPbuf;
-
f2.sPbuf = NULL;
-
frame_list.pop( );
-
Sleep(10);
-
printf("%d\n",i);
-
}
-
return 0;
-
}
在VS2010中編譯並運行上面的代碼時,發現隨着pop()的調用,內存佔用並沒有減少。解決方法有以下幾種:
l 使用list來替代queue,經測試是可行的,在pop的時候內存會減少。但是list的效率要遠不如queue了。
l 考慮使用別的編譯器,例如gcc,內存也會正常地減少。
l 自己寫一個Queue。
貼出一個可以正常減少內存的自定義的Queue代碼:
-
template<typename Data>
-
class concurrent_queue
-
{
-
private:
-
int _size;
-
struct queue_block
-
{
-
Data q[ 0x40 ];
-
unsigned short head, tail;
-
queue_block *next;
-
queue_block( ) { head = tail = 0; next = NULL; }
-
};
-
queue_block *head, *tail;
-
mutable boost::mutex the_mutex;
-
public:
-
concurrent_queue( ) { head = tail = NULL; }
-
~concurrent_queue( )
-
{
-
while ( head )
-
{
-
queue_block *p = head;
-
head = head->next;
-
delete p;
-
}
-
}
-
void push( const Data& data )
-
{
-
boost::mutex::scoped_lock lock( the_mutex );
-
if ( !head )
-
head = tail = new queue_block;
-
if ( ( ( tail->tail + 1 ) & 0x3f ) == tail->head )
-
{
-
tail->next = new queue_block;
-
tail = tail->next;
-
}
-
tail->q[ tail->tail ] = data;
-
tail->tail = ( tail->tail + 1 ) & 0x3f;
-
_size ++;
-
}
-
bool empty( ) const
-
{
-
boost::mutex::scoped_lock lock( the_mutex );
-
return head == NULL;
-
}
-
Data& front( )
-
{
-
boost::mutex::scoped_lock lock( the_mutex );
-
return head->q[ head->head ];
-
}
-
Data const& front( ) const
-
{
-
boost::mutex::scoped_lock lock( the_mutex );
-
return head->q[ head->head ];
-
}
-
void pop( )
-
{
-
boost::mutex::scoped_lock lock( the_mutex );
-
head->head = ( head->head + 1 ) & 0x3f;
-
if ( head->head == head->tail )
-
{
-
queue_block *p = head;
-
head = head->next;
-
delete p;
-
}
-
_size --;
-
}
-
int size( )
-
{
-
boost::mutex::scoped_lock lock( the_mutex );
-
return _size;
-
}
-
};