Std: nth_element crash

Source: Internet
Author: User

Std: nth_element crash

(1) Source Code:

 
 
  1. auto less_compare = [] (const MirroringGroup& mg1, const MirroringGroup& mg2) -> bool {
  2. return (mg1.usage() < mg2.usage());
  3. };
  4. std::nth_element(mgs->begin(), mgs->begin() + (copy_count - 1), mgs->end(), less_compare);

(2) Problem:

Crash occurs frequently. The stack is as follows:

 
 
  1. #0 0x00000000004b3807 in MirroringGroup::CopyFrom (this=0x15edf20, from=...) at miuifs/miuistorage-dev/idl/proto/InternalData.pb.cc:6487
  2. #1 0x000000000052bc71 in MirroringGroup::operator= (this=0x15edf20, from=...) at miuifs/miuistorage-dev/idl/proto/InternalData.pb.h:1797
  3. #2 0x000000000052f7cb in std::swap (__a=..., __b=...) at /usr/local/include/c++/4.8.2/bits/move.h:177
  4. #3 0x000000000052e0b0 in std::iter_swap<__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > > > (__a=..., __b=...)
  5. at /usr/local/include/c++/4.8.2/bits/stl_algobase.h:147
  6. #4 0x0000000000604b11 in std::__unguarded_partition<__gnu_cxx::__normal_iterator >, MirroringGroup, miuifs::BlockManager::ChooseWritableMirroringGroups(std::vector *, int)::__lambda101>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, const MirroringGroup &, miuifs::BlockManager::__lambda101) (__first=..., __last=..., __pivot=..., __comp=...) at /usr/local/include/c++/4.8.2/bits/stl_algo.h:2270
  7. #5 0x0000000000603c1b in std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator >, miuifs::BlockManager::ChooseWritableMirroringGroups(std::vector *, int)::__lambda101>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, miuifs::BlockManager::__lambda101) (
  8. __first=..., __last=..., __comp=...) at /usr/local/include/c++/4.8.2/bits/stl_algo.h:2296
  9. #6 0x0000000000603408 in std::__introselect<__gnu_cxx::__normal_iterator >, long int, miuifs::BlockManager::ChooseWritableMirroringGroups(std::vector *, int)::__lambda101>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, long, miuifs::BlockManager::__lambda101) (__first=..., __nth=..., __last=..., __depth_limit=2,
  10. __comp=...) at /usr/local/include/c++/4.8.2/bits/stl_algo.h:2394
  11. #7 0x0000000000602c95 in std::nth_element<__gnu_cxx::__normal_iterator >, miuifs::BlockManager::ChooseWritableMirroringGroups(std::vector *, int)::__lambda101>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, miuifs::BlockManager::__lambda101) (__first=..., __nth=..., __last=..., __comp=...)
  12. at /usr/local/include/c++/4.8.2/bits/stl_algo.h:5417
  13. #8 0x000000000060039c in miuifs::BlockManager::ChooseWritableMirroringGroups (this=0x118abe0 , mgs=0x7fffeb9f4140,
  14. copy_count=2) at miuifs/miuistorage-dev/BlockManager.cc:391
  15. #9 0x00000000005ff9cf in miuifs::BlockManager::NewBlock (this=0x118abe0 ) at miuifs/miuistorage-dev/BlockManager.cc:331
  16. #10 0x00000000005fed63 in miuifs::BlockManager::AcquireBlock (this=0x118abe0 , attribute=...)
  17. at miuifs/miuistorage-dev/BlockManager.cc:243

(3) Search for problems:

The problem has been found in std: nth_element. At first, I didn't think of the STL problem, and there was no good solution, later, I found the cause by reading the STL source code in/usr/local/include/c ++/4.8.2/bits/stl_algo.h:

 
 
  1. template
  2. inline _RandomAccessIterator
  3. __unguarded_partition_pivot(_RandomAccessIterator __first,
  4. _RandomAccessIterator __last, _Compare __comp)
  5. {
  6. _RandomAccessIterator __mid = __first + (__last - __first) / 2;
  7. std::__move_median_to_first(__first, __first + 1, __mid, (__last - 2),
  8. __comp);
  9. return std::__unguarded_partition(__first + 1, __last, *__first, __comp);
  10. }

The _ move_median_to_first function exchanges the values of the intermediate sizes in _ first + 1, _ mid, (_ last-2) with _ first. However, the _ mid (_ last-2) point to the same iterator is ignored. If the input is as follows:


The result after _ move_median_to_first is as follows:


_ First points to the maximum value. Then, let's take a look at the implementation of std ::__ unguarded_partition. In row 2263 _ comp (* _ first, _ partition), true is always returned, as a result, ++ _ first has been executed and illegal memory is accessed.


 
 
  1. template
  2. _RandomAccessIterator
  3. __unguarded_partition(_RandomAccessIterator __first,
  4. _RandomAccessIterator __last,
  5. const _Tp& __pivot, _Compare __comp)
  6. {
  7. while (true)
  8. {
  9. while (__comp(*__first, __pivot))
  10. ++__first;
  11. --__last;
  12. while (__comp(__pivot, *__last))
  13. --__last;
  14. if (!(__first < __last))
  15. return __first;
  16. std::iter_swap(__first, __last);
  17. ++__first;
  18. }
  19. }

(4) solution:

Google found the following link and found that it was indeed a STL bug. It could only be solved by upgrading C ++.

Https://bugs.debian.org/cgi-bin/bugreport.cgi? Bug = 732042





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.