最近在使用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;
        }
}; 
                
                  
                  
                  
                  
                            
本文探讨了std::queue在内存管理上的特殊行为,尤其是在连续push和pop操作中内存占用不减的问题。通过对比不同容器如list的表现,以及在不同编译器下的测试结果,作者提出了解决方案,包括使用自定义的并发队列实现。
          
      
          
                
                
                
                
              
                
                
                
                
                
              
                
                
              
            
                  
					7万+
					
被折叠的  条评论
		 为什么被折叠?
		 
		 
		
    
  
    
  
            


            