std::nth_element crash问题_PHP教程
std::nth_element crash问题
(1) 源码:
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>auto less_compare = [] (const MirroringGroup& mg1, const MirroringGroup& mg2) -> bool {<br /> </li><li>return (mg1.usage() < mg2.usage());<br /></li><li>};<br /></li><li>std::nth_element(mgs->begin(), mgs->begin() + (copy_count - 1), mgs->end(), less_compare); </li></ol>
(2) 问题:
经常发生crash,stack如下:
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>#0 0x00000000004b3807 in MirroringGroup::CopyFrom (this=0x15edf20, from=...) at miuifs/miuistorage-dev/idl/proto/InternalData.pb.cc:6487<br /> </li><li>#1 0x000000000052bc71 in MirroringGroup::operator= (this=0x15edf20, from=...) at miuifs/miuistorage-dev/idl/proto/InternalData.pb.h:1797<br /></li><li>#2 0x000000000052f7cb in std::swap<MirroringGroup> (__a=..., __b=...) at /usr/local/include/c++/4.8.2/bits/move.h:177<br /></li><li>#3 0x000000000052e0b0 in std::iter_swap<__gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, __gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > > > (__a=..., __b=...)<br /></li><li>at /usr/local/include/c++/4.8.2/bits/stl_algobase.h:147<br /></li><li>#4 0x0000000000604b11 in std::__unguarded_partition<__gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup> >, MirroringGroup, miuifs::BlockManager::ChooseWritableMirroringGroups(std::vector<MirroringGroup>*, int)::__lambda101>(__gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, __gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, const MirroringGroup &, miuifs::BlockManager::__lambda101) (__first=..., __last=..., __pivot=..., __comp=...) at /usr/local/include/c++/4.8.2/bits/stl_algo.h:2270<br /></li><li>#5 0x0000000000603c1b in std::__unguarded_partition_pivot<__gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup> >, miuifs::BlockManager::ChooseWritableMirroringGroups(std::vector<MirroringGroup>*, int)::__lambda101>(__gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, __gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, miuifs::BlockManager::__lambda101) (<br /></li><li>__first=..., __last=..., __comp=...) at /usr/local/include/c++/4.8.2/bits/stl_algo.h:2296<br /></li><li>#6 0x0000000000603408 in std::__introselect<__gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup> >, long int, miuifs::BlockManager::ChooseWritableMirroringGroups(std::vector<MirroringGroup>*, int)::__lambda101>(__gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, __gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, __gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, long, miuifs::BlockManager::__lambda101) (__first=..., __nth=..., __last=..., __depth_limit=2, <br /></li><li>__comp=...) at /usr/local/include/c++/4.8.2/bits/stl_algo.h:2394<br /></li><li>#7 0x0000000000602c95 in std::nth_element<__gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup> >, miuifs::BlockManager::ChooseWritableMirroringGroups(std::vector<MirroringGroup>*, int)::__lambda101>(__gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, __gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, __gnu_cxx::__normal_iterator<MirroringGroup*, std::vector<MirroringGroup, std::allocator<MirroringGroup> > >, miuifs::BlockManager::__lambda101) (__first=..., __nth=..., __last=..., __comp=...)<br /></li><li>at /usr/local/include/c++/4.8.2/bits/stl_algo.h:5417<br /></li><li>#8 0x000000000060039c in miuifs::BlockManager::ChooseWritableMirroringGroups (this=0x118abe0 <miuifs::BlockManager::Instance()::instance>, mgs=0x7fffeb9f4140, <br /></li><li>copy_count=2) at miuifs/miuistorage-dev/BlockManager.cc:391<br /></li><li>#9 0x00000000005ff9cf in miuifs::BlockManager::NewBlock (this=0x118abe0 <miuifs::BlockManager::Instance()::instance>) at miuifs/miuistorage-dev/BlockManager.cc:331<br /></li><li>#10 0x00000000005fed63 in miuifs::BlockManager::AcquireBlock (this=0x118abe0 <miuifs::BlockManager::Instance()::instance>, attribute=...)<br /></li><li>at miuifs/miuistorage-dev/BlockManager.cc:243</li></ol>
(3) 查找问题:
问题一直出现在std::nth_element中,开始没有想到是STL的问题,一直没有很好的解决办法,后来通过阅读STL源码找到原因在/usr/local/include/c++/4.8.2/bits/stl_algo.h中:
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>template<typename _RandomAccessIterator, typename _Compare><br /> </li><li>inline _RandomAccessIterator<br /></li><li>__unguarded_partition_pivot(_RandomAccessIterator __first,<br /></li><li>_RandomAccessIterator __last, _Compare __comp)<br /></li><li>{<br /></li><li>_RandomAccessIterator __mid = __first + (__last - __first) / 2;<br /></li><li>std::__move_median_to_first(__first, __first + 1, __mid, (__last - 2),<br /></li><li>__comp);<br /></li><li>return std::__unguarded_partition(__first + 1, __last, *__first, __comp);<br /></li><li>} </li></ol>
__move_median_to_first函数的作用是将 __first +1 , __mid, (__last - 2) 中中间大小的值和 __first交换。但是却忽略了__mid,(__last - 2) 指向相同迭代器的情况,如果输入时情况如下:

经过__move_median_to_first之后的结果如下:

此时__first指向了最大的值。然后看std::__unguarded_partition的实现,在2263行__comp(*__first, __pivot))永远返回true,导致++__first一直执行而访问了非法内存。
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>template<typename _RandomAccessIterator, typename _Tp, typename _Compare><br /> </li><li>_RandomAccessIterator<br /></li><li>__unguarded_partition(_RandomAccessIterator __first,<br /></li><li>_RandomAccessIterator __last,<br /></li><li>const _Tp& __pivot, _Compare __comp)<br /></li><li>{<br /></li><li>while (true)<br /></li><li>{<br /></li><li>while (__comp(*__first, __pivot))<br /></li><li>++__first;<br /></li><li>--__last;<br /></li><li>while (__comp(__pivot, *__last))<br /></li><li>--__last;<br /></li><li>if (!(__first < __last))<br /></li><li>return __first;<br /></li><li>std::iter_swap(__first, __last);<br /></li><li>++__first;<br /></li><li>}<br /></li><li>} </li></ol>
(4) 解决方法:
通过google找到下面这个链接,发现确实是一个STL的bug,只能通过升级C++解决了。
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=732042

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Ces derniers jours, Ice Universe n'a cessé de révéler des détails sur le Galaxy S25 Ultra, qui est largement considéré comme le prochain smartphone phare de Samsung. Entre autres choses, le fuyard a affirmé que Samsung prévoyait d'apporter une seule mise à niveau de l'appareil photo.

OnLeaks s'est désormais associé à Android Headlines pour offrir un premier aperçu du Galaxy S25 Ultra, quelques jours après une tentative infructueuse de générer plus de 4 000 $ auprès de ses abonnés X (anciennement Twitter). Pour le contexte, les images de rendu intégrées ci-dessous h

En plus d'annoncer deux nouveaux smartphones, TCL a également annoncé une nouvelle tablette Android appelée NXTPAPER 14, et sa taille d'écran massive est l'un de ses arguments de vente. Le NXTPAPER 14 est doté de la version 3.0 de la marque emblématique de panneaux LCD mats de TCL.

Le Vivo Y300 Pro vient d'être entièrement dévoilé et c'est l'un des téléphones Android de milieu de gamme les plus fins avec une grande batterie. Pour être exact, le smartphone ne fait que 7,69 mm d'épaisseur mais dispose d'une batterie de 6 500 mAh. C'est la même capacité que le lancement récent

Samsung n'a pas encore donné d'indications sur la date à laquelle il mettrait à jour sa série de smartphones Fan Edition (FE). Dans l’état actuel des choses, le Galaxy S23 FE reste l’édition la plus récente de la société, ayant été présentée début octobre 2023. Cependant, de nombreux

Ces derniers jours, Ice Universe n'a cessé de révéler des détails sur le Galaxy S25 Ultra, qui est largement considéré comme le prochain smartphone phare de Samsung. Entre autres choses, le fuyard a affirmé que Samsung prévoyait d'apporter une seule mise à niveau de l'appareil photo.

Le Redmi Note 14 Pro Plus est désormais officiel en tant que successeur direct du Redmi Note 13 Pro Plus de l'année dernière (375 $ sur Amazon). Comme prévu, le Redmi Note 14 Pro Plus est en tête de la série Redmi Note 14 aux côtés du Redmi Note 14 et du Redmi Note 14 Pro. Li

La marque sœur de OnePlus, iQOO, a un cycle de produits 2023-4 qui pourrait être presque terminé ; néanmoins, la marque a déclaré qu'elle n'en avait pas encore fini avec sa série Z9. Sa variante Turbo+ finale, et peut-être la plus haut de gamme, vient d'être annoncée comme prévu. T
