[cfe-dev] libc++ std::map self-assignment bug

Sean Silva silvas at purdue.edu
Sat Nov 30 20:02:59 PST 2013


On Fri, Nov 29, 2013 at 11:42 AM, Howard Hinnant <hhinnant at apple.com> wrote:

>
> On Nov 29, 2013, at 2:50 AM, Kal <b17c0de at gmail.com> wrote:
>
> > Am 29.11.13 04:17, schrieb Howard Hinnant:
> >> On Nov 28, 2013, at 9:58 PM, Karen Shaeffer <shaeffer at neuralscape.com>
> wrote:
> >>
> >>> On Fri, Nov 29, 2013 at 02:19:44AM +0100, Kal wrote:
> >>>> Hi Howard, etc,
> >>>>
> >>>> libc++3.4 (rc1/trunk) std::map doesn't support self-assignment for
> std <
> >>>> c++11. The relevant code is:
> >>>>
> >>>>   _LIBCPP_INLINE_VISIBILITY
> >>>>   map& operator=(const map& __m)
> >>>>       {
> >>>> #if __cplusplus >= 201103L
> >>>>           __tree_ = __m.__tree_;
> >>>> #else
> >>>>           __tree_.clear();
> >>>>           __tree_.value_comp() = __m.__tree_.value_comp();
> >>>>           __tree_.__copy_assign_alloc(__m.__tree_);
> >>>>           insert(__m.begin(), __m.end());
> >>>> #endif
> >>>>           return *this;
> >>>>       }
> >>>>
> >>>> Maybe should be like:
> >>>>
> >>>>   _LIBCPP_INLINE_VISIBILITY
> >>>>   map& operator=(const map& __m)
> >>>>       {
> >>>> #if __cplusplus >= 201103L
> >>>>           __tree_ = __m.__tree_;
> >>>> #else
> >>>>           if (this != &__m) {
> >>>>               __tree_.clear();
> >>>>               __tree_.value_comp() = __m.__tree_.value_comp();
> >>>>               __tree_.__copy_assign_alloc(__m.__tree_);
> >>>>               insert(__m.begin(), __m.end());
> >>>>           }
> >>>> #endif
> >>>>           return *this;
> >>>>       }
> >>>>
> >>>> I see the same issue with unordered_map& operator=(const
> unordered_map&
> >>>> __u).
> >>>>
> >>>> Thanks!
> >>>> Kal
> >>> --- end quoted text ---
> >>>
> >>> Hi Kal,
> >>> I don't speak for Howard or anyone else. But my understanding is the
> stl library
> >>> generally doesn't perform checks like that with the goal of best
> possible performance.
> >>> I see a lot of code in stdlibc++ just like that.
> >> Actually this does look like a bug to me (for  __cplusplus < 201103L).
>  I think Kal has the correct fix.  A post-condition of copy assignment is
> that both lhs and rhs should be equivalent to the previous value of rhs.
>  For move assignment this is not the case.  But this is copy assignment.
> >>
> >> Howard
> >>
> > Hi Howard,
> > Thanks for the reply. Do you think a fix for this will be committed for
> > the 3.4 release?
>
> I don't know.
>
> >
> > Also could you explain why the special check for __cplusplus < 201103L
> > is necessary at all. Both branches are doing almost the same thing
> > (looking into the implementation of __tree). Is there some subtle
> > difference in the standard that requires a different implementation here?
>
> C++11 introduces the possibility of recycling nodes of [multi]map under
> the copy assignment operator by pushing the requirements on
> [multi]map::value_type down to the key_type and mapped_type (23.2.4
> [associative.reqmts]/p7).  To actually implement this optimization I used
> new C++11 language features of union, which do not compile when -std=c++03.
>
> In C++11, using libc++, if two equal sized map<int, int> are assigned,
> there are zero trips to the heap.  The nodes in the lhs are assigned new
> values, and rebalancing takes place as necessary.


In what situation would rebalancing need to happen during this operation?
If they are the same size, wouldn't you just simultaneously inorder walk
both, assigning element by element (or the equivalent)? The structure of an
rb-tree is independent of the actual values contained.

-- Sean Silva


>  In C++03, the lhs is first clear()'d, and then one does an insert for
> every value in the rhs.
>
> Same design (and bug as you note) in unordered_[multi]map.
>
> Howard
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131130/e95d0e1e/attachment.html>


More information about the cfe-dev mailing list