關於C++的std::queue內存不釋放的問題的解決方法

https://blog.csdn.net/zhoukai216/article/details/89403363

最近在使用std::queue的時候,遇到一些奇怪的問題。我們使用std::queue來存放一些臨時的緩衝數據,然後有一個線程不斷地從queue裏取數據,寫入到文件中,之後會調用pop()函數將數據彈出。但是很奇怪的地在彈出的過程中,程序的內存佔用絲毫沒有減少。查了一些資料後發現,貌似std::queue底層自己有一套內存管理機制,只有在程序退出或是queue被銷燬的時候纔會釋放這一部分內存。筆者使用的測試代碼如下:


 
  1. #include <stdio.h>

  2.  
  3. #include <queue>

  4.  
  5. #include <WinSock2.h>

  6.  
  7.  
  8.  
  9. template<typename Data>

  10.  
  11. class concurrent_queue

  12.  
  13. {

  14.  
  15. private:

  16.  
  17. std::queue<Data> the_queue;

  18.  
  19. public:

  20.  
  21. void push( const Data& data )

  22.  
  23. {

  24.  
  25. the_queue.push( data );

  26.  
  27. }

  28.  
  29. bool empty( ) const

  30.  
  31. {

  32.  
  33. return the_queue.empty( );

  34.  
  35. }

  36.  
  37. Data& front( )

  38.  
  39. {

  40.  
  41. return the_queue.front( );

  42.  
  43. }

  44.  
  45. Data const& front( ) const

  46.  
  47. {

  48.  
  49. return the_queue.front( );

  50.  
  51. }

  52.  
  53. void pop( )

  54.  
  55. {

  56.  
  57. the_queue.pop( );

  58.  
  59. }

  60.  
  61. int size( )

  62.  
  63. {

  64.  
  65. return the_queue.size( );

  66.  
  67. }

  68.  
  69. };

  70.  
  71.  
  72.  
  73. typedef struct FRAME

  74.  
  75. {

  76.  
  77. unsigned char* sPbuf;

  78.  
  79. int iSize;

  80.  
  81. };

  82.  
  83.  
  84.  
  85. int main() {

  86.  
  87. concurrent_queue<FRAME> frame_list;

  88.  
  89. FRAME f;

  90.  
  91.  
  92.  
  93. // push

  94.  
  95. for (int i = 0; i < 100000; i ++ ) {

  96.  
  97. FRAME f;

  98.  
  99. f.sPbuf = NULL;

  100.  
  101. f.sPbuf = new byte[ 1000 ];

  102.  
  103. f.iSize = 1000;

  104.  
  105. frame_list.push( f );

  106.  
  107. }

  108.  
  109. // pop

  110.  
  111. for (int i = 0; i < 100000; i ++ ) {

  112.  
  113. FRAME f2 = frame_list.front( );

  114.  
  115. delete [] f2.sPbuf;

  116.  
  117. f2.sPbuf = NULL;

  118.  
  119. frame_list.pop( );

  120.  
  121. Sleep(10);

  122.  
  123. printf("%d\n",i);

  124.  
  125.  
  126.  
  127. }

  128.  
  129. return 0;

  130.  
  131. }

在VS2010中編譯並運行上面的代碼時,發現隨着pop()的調用,內存佔用並沒有減少。解決方法有以下幾種:

l 使用list來替代queue,經測試是可行的,在pop的時候內存會減少。但是list的效率要遠不如queue了。

l 考慮使用別的編譯器,例如gcc,內存也會正常地減少。

l 自己寫一個Queue。

貼出一個可以正常減少內存的自定義的Queue代碼:


 
  1. template<typename Data>

  2.  
  3. class concurrent_queue

  4.  
  5. {

  6.  
  7. private:

  8.  
  9. int _size;

  10.  
  11. struct queue_block

  12.  
  13. {

  14.  
  15. Data q[ 0x40 ];

  16.  
  17. unsigned short head, tail;

  18.  
  19. queue_block *next;

  20.  
  21. queue_block( ) { head = tail = 0; next = NULL; }

  22.  
  23. };

  24.  
  25. queue_block *head, *tail;

  26.  
  27.  
  28.  
  29. mutable boost::mutex the_mutex;

  30.  
  31. public:

  32.  
  33.  
  34.  
  35. concurrent_queue( ) { head = tail = NULL; }

  36.  
  37. ~concurrent_queue( )

  38.  
  39. {

  40.  
  41. while ( head )

  42.  
  43. {

  44.  
  45. queue_block *p = head;

  46.  
  47. head = head->next;

  48.  
  49. delete p;

  50.  
  51. }

  52.  
  53. }

  54.  
  55. void push( const Data& data )

  56.  
  57. {

  58.  
  59. boost::mutex::scoped_lock lock( the_mutex );

  60.  
  61. if ( !head )

  62.  
  63. head = tail = new queue_block;

  64.  
  65. if ( ( ( tail->tail + 1 ) & 0x3f ) == tail->head )

  66.  
  67. {

  68.  
  69. tail->next = new queue_block;

  70.  
  71. tail = tail->next;

  72.  
  73. }

  74.  
  75. tail->q[ tail->tail ] = data;

  76.  
  77. tail->tail = ( tail->tail + 1 ) & 0x3f;

  78.  
  79. _size ++;

  80.  
  81. }

  82.  
  83. bool empty( ) const

  84.  
  85. {

  86.  
  87. boost::mutex::scoped_lock lock( the_mutex );

  88.  
  89. return head == NULL;

  90.  
  91. }

  92.  
  93. Data& front( )

  94.  
  95. {

  96.  
  97. boost::mutex::scoped_lock lock( the_mutex );

  98.  
  99. return head->q[ head->head ];

  100.  
  101. }

  102.  
  103. Data const& front( ) const

  104.  
  105. {

  106.  
  107. boost::mutex::scoped_lock lock( the_mutex );

  108.  
  109. return head->q[ head->head ];

  110.  
  111. }

  112.  
  113. void pop( )

  114.  
  115. {

  116.  
  117. boost::mutex::scoped_lock lock( the_mutex );

  118.  
  119. head->head = ( head->head + 1 ) & 0x3f;

  120.  
  121. if ( head->head == head->tail )

  122.  
  123. {

  124.  
  125. queue_block *p = head;

  126.  
  127. head = head->next;

  128.  
  129. delete p;

  130.  
  131. }

  132.  
  133. _size --;

  134.  
  135. }

  136.  
  137. int size( )

  138.  
  139. {

  140.  
  141. boost::mutex::scoped_lock lock( the_mutex );

  142.  
  143. return _size;

  144.  
  145. }

  146.  
  147. };

此文章轉載自http://blog.sina.com.cn/s/blog_3fe961ae0101gef9.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章