{"id":108587,"date":"2023-08-10T07:00:00","date_gmt":"2023-08-10T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=108587"},"modified":"2023-08-10T11:47:22","modified_gmt":"2023-08-10T18:47:22","slug":"20230810-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230810-00\/?p=108587","title":{"rendered":"Inside STL: The deque, implementation"},"content":{"rendered":"<p>Now that we understand <a title=\"Inside STL: The deque, design\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20230809-00\/?p=108577\"> the design behind the common STL dequeue implementations<\/a>, we can peek into the implementation details.<\/p>\n<p>All three of the major implementations of the standard library maintain an array of pointers to blocks, which they confusingly call a &#8220;map&#8221; even though it is unrelated to <code>std::map<\/code>. (Even more confusingly, gcc internally uses the term &#8220;node&#8221; instead of &#8220;block&#8221;.) Initially, all the pointers in the map are <code>nullptr<\/code>, and the blocks are allocated only on demand.<\/p>\n<p>We will say that a block is <i>spare<\/i> if it contains only spare elements.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>\u00a0<\/th>\n<th width=\"28%\">gcc<\/th>\n<th width=\"28%\">clang<\/th>\n<th width=\"28%\">msvc<\/th>\n<\/tr>\n<tr>\n<td>Block size<\/td>\n<td>as many as fit in 512 bytes but at least 1 element<\/td>\n<td>as many as fit in 4096 bytes but at least 16 elements<\/td>\n<td>power of 2 that fits in 16 bytes but at least 1 element<\/td>\n<\/tr>\n<tr>\n<td>Initial map size<\/td>\n<td>8<\/td>\n<td>2<\/td>\n<td>8<\/td>\n<\/tr>\n<tr>\n<td>Map growth<\/td>\n<td>2\u00d7<\/td>\n<td>2\u00d7<\/td>\n<td>2\u00d7<\/td>\n<\/tr>\n<tr>\n<td>Map shrinkage<\/td>\n<td>On request<\/td>\n<td>On request<\/td>\n<td>On request<\/td>\n<\/tr>\n<tr>\n<td>Initial first\/last<\/td>\n<td>Center<\/td>\n<td>Start<\/td>\n<td>Start<\/td>\n<\/tr>\n<tr>\n<td>Members<\/td>\n<td valign=\"baseline\"><tt>block** map;<\/p>\n<p>\nsize_t map_size;<br \/>\niterator first;<br \/>\niterator last;<\/tt><\/td>\n<td valign=\"baseline\"><tt>block** map;<br \/>\nblock** first_block;<br \/>\nblock** last_block;<br \/>\nblock** end_block;<br \/>\nsize_t first;<br \/>\nsize_t size;<\/tt><\/td>\n<td valign=\"baseline\"><tt>block** map;<\/p>\n<p>\nsize_t map_size;<br \/>\nsize_t first;<br \/>\nsize_t size;<\/tt><\/td>\n<\/tr>\n<tr>\n<td>Map layout<\/td>\n<td>counted array<\/td>\n<td><tt>simple_deque<\/tt><\/td>\n<td>counted array<\/td>\n<\/tr>\n<tr>\n<td>Valid range<\/td>\n<td>Pair of iterators<\/td>\n<td>Start and count<\/td>\n<td>Start and count<\/td>\n<\/tr>\n<tr>\n<td>Iterator<\/td>\n<td style=\"font-size: 80%;\"><tt>T* current;<br \/>\nT* current_block_begin;<br \/>\nT* current_block_end;<br \/>\nblock** current_block;<\/tt><\/td>\n<td style=\"font-size: 80%;\">T* current;<\/p>\n<p>\nblock** current_block;<\/td>\n<td style=\"font-size: 80%;\" valign=\"baseline\"><tt>deque* parent;<br \/>\nsize_t index;<\/tt><\/td>\n<\/tr>\n<tr>\n<td><code>begin()<\/code> \/<br \/>\n<code>end()<\/code><\/td>\n<td>Copy <code>first<\/code> and <code>last<\/code>.<\/td>\n<td>Break <code>first<\/code> and <code>first + size<\/code> into block index and offset.<\/td>\n<td>Break <code>first<\/code> and <code>first + size<\/code> into block index and offset.<\/td>\n<\/tr>\n<tr>\n<td>Spare blocks<\/td>\n<td>Aggressively pruned<\/td>\n<td>Keep one on each end<\/td>\n<td>Keep all<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The Microsoft Visual C++ implementation has a tiny block size. I suspect this decision was made a long time ago, and the Visual C++ folks are anxious to bump up the block size at the next ABI break.<\/p>\n<p>The gcc implementation doesn&#8217;t believe in spare blocks; it frees blocks as soon as they become empty. The clang and Visual C++ implementations hold onto spare blocks in anticipation that they will be needed again soon. The clang implementation retains one spare block at each end, whereas the Visual C++ implementation retains all spare blocks. (I suspect this is another old design decision that the Visual C++ team wants to change at the next ABI break.)<\/p>\n<p>If the clang implementation needs to allocate a new block at one end, it first checks to see if there is a spare block at the other end. If so, then it moves that block from one end to the other instead of allocating a new block.<\/p>\n<p>The Microsoft Visual C++ implementation treats the map as a <i>circular<\/i> array of blocks. This means that once the map is filled with blocks, no further allocations or element movement is needed to satisfy any further deque operations, assuming the size of the dequeue never exceeds the capacity.<\/p>\n<p>None of the three implementations shrinks the map automatically. You have to call <code>shrink_<wbr \/>to_<wbr \/>fit()<\/code> to get the map to shrink.<\/p>\n<p>All three implementations keep track of the blocks differently. The gcc and Visual C++ implementations use a simple counted array. If the gcc implementation runs out of map entries at one end, it slides the in-use blocks so that they are centered in the block map. The Visual C++ implementation uses a circular buffer, so the only time it runs out of map entries is when the entire map needs to be expanded. The clang implementation gets fancy and uses the equivalent of our <code>simple_deque<\/code> for its map. This allows it to use the &#8220;slide&#8221; trick to shift an empty slot from one end to the other.<\/p>\n<p>All three implementations choose different formats for their iterators. The gcc and clang implementations use a pointer to the current element and a pointer to the current block. When incrementing or decrementing off the end of the block, they increment or decrement the <code>current_block<\/code> to find the next block. The gcc implementation carries extra values <code>current_block_begin<\/code> and <code>current_block_end<\/code>, which are technically redundant, since you can derive<\/p>\n<ul>\n<li><code>current_block_begin = *current_block;<\/code><\/li>\n<li><code>current_block_end = current_block_begin + block_size;<\/code><\/li>\n<\/ul>\n<p>Not only are these iterators bulky (presumably for performance?), but the gcc implementation stores these bulky iterators in its <code>deque<\/code>, whereas clang and Visual C++ use an index and length. Accessing an element by index involves dividing by the block size. This means that clang&#8217;s <code>begin()<\/code> and <code>end()<\/code> incur a runtime division to calculate which block the element is in and using the remainder to get the offset within the block. Visual C++ forces block sizes to be powers of two, so it can use bitwise operations to break the index into a block and offset.<\/p>\n<p>Here&#8217;s a visualization of what the three <code>deque<\/code> implementations look like if you alternately pop from the front and push to the back:<\/p>\n<p>First, here&#8217;s what gcc&#8217;s implementation does.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" title=\"See row descriptions. Each row describes the contents of a map with potentially four entries.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td colspan=\"2\">map[0]<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">map[1]<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">map[2]<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">map[3]<\/td>\n<\/tr>\n<tr title=\"Map entry 0 is unallocated. Map entry 1 points to a block called A whose contents are a spare element and the element 1. Map entry 2 points to a block called B whose contents are the elements 2 and 3. Map entry 3 is unallocated.\">\n<td colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">1<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">pop 1 from the front: Free block A<\/td>\n<\/tr>\n<tr title=\"Map entry 0 is unallocated. Map entry 1 is recently unallocated. Map entry 2 points to a block called B whose contents are the elements 2 and 3. Map entry 3 is unallocated.\">\n<td style=\"border: none 1px currentcolor;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: dashed 1px currentcolor;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: none 1px currentcolor;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em; border: none 1px currentcolor;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: dashed 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: dashed 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em; border: none 1px currentcolor;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">push 4 to the back: Allocate block C<\/td>\n<\/tr>\n<tr title=\"Map entries 0 and 1 are unallocated. Map entry 2 points to a block called B whose contents are the elements 2 and 3. Map entry 3 points to a block called C whose elements are the element 4 and a spare element.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">pop 2 from the front<\/td>\n<\/tr>\n<tr title=\"Map entries 0 and 1 are unallocated. Map entry 2 points to a block called B whose contents are a spare element and the element 3. Map entry 3 points to a block called C whose elements are the element 4 and a spare element.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">push 5 to the back<\/td>\n<\/tr>\n<tr title=\"Map entries 0 and 1 are unallocated. Map entry 2 points to a block called B whose contents are a spare element and the element 3. Map entry Block 3 points to a block called C whose elements are elements 4 and 5.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">5<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">pop 3 from the front: Free block B<\/td>\n<\/tr>\n<tr title=\"Map entries 0 and 1 are unallocated. Map entry 2 is recently deallocated. Map entry 3 points to a block called C whose elements are elements 4 and 5.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: dashed 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: dashed 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: dashed 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">5<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">push 6 to the back: Allocate block D and slide<\/td>\n<\/tr>\n<tr title=\"Map entries 0 is unallocated. Map entry 1 is now the block called C (previously block 3) whose elements are elements 4 and 5. Map entry 2 is a new-allocated block called D containing the element 6 and a spare element. Map entry 3 is unallocated.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">D<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">5<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">6<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The eager pruning of empty blocks in gcc means that we free a block, only to immediately allocate a new one.<\/p>\n<p>Here&#8217;s what clang does when you alternate pops and pushes:<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td colspan=\"2\">map[0]<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">map[1]<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">map[2]<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">map[3]<\/td>\n<\/tr>\n<tr title=\"Map entry 0 is unallocated. Map entry 1 points to a block called A whose contents are a spare element and the element 1. Map entry 2 points to a block called B whose contents are the elements 2 and 3. Map entry 3 is unallocated.\">\n<td colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">1<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">pop 1 from the front: Block A becomes spare<\/td>\n<\/tr>\n<tr title=\"Map entry 0 is unallocated. Map entry 1 contains two empty elements. Map entry 2 points to a block called B whose contents are the elements 2 and 3. Map entry 3 is unallocated.\">\n<td colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em; border: none 1px currentcolor;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em; border: none 1px currentcolor;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">push 4 to the back: Steal block A<\/td>\n<\/tr>\n<tr title=\"Map entry 0 is unallocated. Map entry 1 is now unallocated; the block it pointed to is now map entry 3. Map entry 2 points to a block called B whose contents are the elements 2 and 3. Map entry 3 points to block A (formerly pointed to by map entry 1) with element 5 and a spare element.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">pop 2 from the front<\/td>\n<\/tr>\n<tr title=\"Map entries 0 and 1 are unallocated. Map entry 2 points to a block called B whose contents are a spare element and the element 3. Map entry 3 points to a block called A with element 4 and a spare element.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">push 5 to the back<\/td>\n<\/tr>\n<tr title=\"Map entries 0 and 1 are unallocated. Map entry 2 points to a block called B whose contents are a spare element and the element 3. Map entry 3 points to a block called A with elements 4 and 5.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">5<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">pop 3 from the front: Block B becomes spare<\/td>\n<\/tr>\n<tr title=\"Map entries 0 and 1 are unallocated. Map entry 2 points to a block called B whose contents are empty. Map entry 3 points to a block called A with elements 4 and 5.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">5<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">push 6 to the back: Steal block B and slide<\/td>\n<\/tr>\n<tr title=\"Map entry 0 is unallocated. Map entry 1 points to Block A (formerly pointed to by block 3) containing elements 4 and 5. Map entry 2 points to a block called B whose contents are the element 6 and an empty element. Map entry 3 is unallocated.\">\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">5<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">6<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Since clang keeps a one-block spare, the growth on the back can be satisfied by stealing the spare block from the front. No new memory allocations are performed; just block sliding.<\/p>\n<p>And here&#8217;s what Visual C++ does. Note that Visual C++ always pushes starting at the start of the map, so getting to the initial state means that we have already popped three elements from the front, leaving a spare block A.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td colspan=\"2\">map[0]<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">map[1]<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">map[2]<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">map[3]<\/td>\n<\/tr>\n<tr title=\"Map entry 0 points to a block called A which is empty. Map entry 1 points to a block called B containing a spare element and the element 1. Map entry 2 points to a block called C whose contents are the elements 2 and 3. Map entry 3 is unallocated.\">\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">1<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">pop 1 from the front: Block B becomes spare<\/td>\n<\/tr>\n<tr title=\"Map entry 0 points to a block called A which is empty. Map entry 1 points to a block called B which is now empty. Map entry 2 points to a block called C whose contents are the elements 2 and 3. Map entry 3 is unallocated.\">\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"width: 4em; border: none 1px currentcolor;\" colspan=\"2\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">push 4 to the back: Allocate block D<\/td>\n<\/tr>\n<tr title=\"Map entry 0 points to a block called A which is empty. Map entry 1 points to a block called B which is empty. Map entry 2 points to a block called C whose contents are the elements 2 and 3. Map entry 3 points to a newly-allocated block D whose contents are the element 4 and a spare element.\">\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">D<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">2<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">pop 2 from the front<\/td>\n<\/tr>\n<tr title=\"Map entry 0 points to a block called A which is empty. Map entry 1 points to a block called B which is empty. Map entry 2 points to a block called C whose contents are an empty element and the element 3. Map entry 3 points to a block D whose contents are the element 4 and a spare element.\">\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">D<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">push 5 to the back<\/td>\n<\/tr>\n<tr title=\"Map entry 0 points to a block called A which is empty. Map entry 1 points to a block called B which is empty. Map entry 2 points to a block called C whose contents are an empty element and the element 3. Map entry 3 points to a block D whose contents are the elements 4 and 5.\">\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">D<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">3<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">5<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">pop 3 from the front: Block C becomes spare<\/td>\n<\/tr>\n<tr title=\"Map entry 0 points to a block called A which is empty. Map entry 1 points to a block called B which is empty. Map entry 2 points to a block called C whose contents are newly-empty. Map entry 3 points to a block D whose contents are the elements 4 and 5.\">\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">D<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">5<\/td>\n<\/tr>\n<tr>\n<td colspan=\"11\" align=\"left\">push 6 to the back: Wrap around to block A<\/td>\n<\/tr>\n<tr title=\"Map entry 0 points to a block called A which contains element 6 and an empty element. Map entry 1 points to a block called B which is empty. Map entry 2 points to a block called C whose contents are empty. Map entry 3 points to a block D whose contents are the elements 4 and 5.\">\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">A<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">B<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">C<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\" colspan=\"2\">D<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">6<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">4<\/td>\n<td style=\"border: solid 1px currentcolor; width: 2em;\">5<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Once you reach the steady state where all the map entries have blocks, further deque operations can be performed without any memory allocation or rearranging.<\/p>\n<p>Here&#8217;s what the Microsoft Visual C++ deque looks like in the debugger with the visualizer:<\/p>\n<pre>d : { size = 0x2 }\r\n    [0x0] = 1 [Type: __int64]\r\n    [0x1] = 2 [Type: __int64]\r\n<\/pre>\n<p>The raw view reveals the soft underbelly of the implementation.<\/p>\n<pre>0:000&gt; ?? d\r\nclass std::deque&lt;__int64,std::allocator&lt;__int64&gt; &gt;\r\n   +0x000 _Mypair          : std::_Compressed_pair&lt;std::allocator&lt;__int64&gt;,std::_Deque_val&lt;std::_Deque_simple_types&lt;__int64&gt; &gt;,1&gt;\r\n0:000&gt; ?? d._Mypair\r\nclass std::_Compressed_pair&lt;std::allocator&lt;__int64&gt;,std::_Deque_val&lt;std::_Deque_simple_types&lt;__int64&gt; &gt;,1&gt;\r\n   +0x000 _Myval2          : std::_Deque_val&lt;std::_Deque_simple_types&lt;__int64&gt; &gt;\r\n0:000&gt; ?? d._Mypair._Myval2\r\nclass std::_Deque_val&lt;std::_Deque_simple_types&lt;__int64&gt; &gt;\r\n   +0x000 _Myproxy         : 0x000001c9`ee615540 std::_Container_proxy\r\n   +0x008 _Map             : 0x000001c9`ee6178b0  -&gt; 0x000001c9`ee615000  -&gt; 0n42\r\n   +0x010 _Mapsize         : 8\r\n   +0x018 _Myoff           : 3\r\n   +0x020 _Mysize          : 2\r\n0:000&gt; dps 0x000001c9`ee6178b0 L 8\r\n000001c9`ee6178b0  000001c9`ee615000\r\n000001c9`ee6178b8  000001c9`ee615160\r\n000001c9`ee6178c0  000001c9`ee615380\r\n000001c9`ee6178c8  000001c9`ee6153c0\r\n000001c9`ee6178d0  000001c9`ee615720\r\n000001c9`ee6178d8  000001c9`ee6155e0\r\n000001c9`ee6178e0  000001c9`ee615240\r\n000001c9`ee6178e8  000001c9`ee615020\r\n0:000&gt; dps 000001c9`ee615160 L2\r\n000001c9`ee615160  00000000`0000002a\r\n000001c9`ee615168  00000000`00000001\r\n0:000&gt; dps 000001c9`ee615380 L2\r\n000001c9`ee615380  00000000`00000002\r\n000001c9`ee615388  00000000`00000099\r\n<\/pre>\n<p>Since this is a dequeue of <code>__int64<\/code> (8 bytes), there will be two values per 16-byte block. From the raw dump, the <code>_Map<\/code> tells us where the block pointers are, and the <code>_Mapsize<\/code> tells us how many. We dump the block pointers, and the <code>_Myoff<\/code> tells us that the first valid entry is at offset 3, and the <code>_Mysize<\/code> tells us that there are two valid entries. Therefore, the first valid entry is at offset 1 in block 1, and the second valid entry is at offset 0 in block 2.<\/p>\n<p>We dump the block at index 1 and see that the value at offset 1 is <code>00000000`00000001<\/code>. And then we dump the block at index 2 and see that the value at offset 0 is <code>00000000`00000002<\/code>. We also see that the other (unused) elements in the block hold values that had previously been pushed and then popped from the deque.<\/p>\n<p><b>Bonus chatter<\/b>: As I noted at the start of the series, the primary purpose of these articles is to explain how to extract the contents of these collection classes when you encounter them in a crash dump. I&#8217;m taking the designs as given and showing how to use them to find the data.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>An array of (pointers to) arrays.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-108587","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>An array of (pointers to) arrays.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108587","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=108587"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/108587\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=108587"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=108587"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=108587"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}