我撰寫了一個程式,該程式使用 a 計算字串的出現次數std::unordered_map,然后將值從映射復制到 astd::vector并呼叫std::sort首先按計數對它們進行排序,然后按字串排序。
請參閱下面的代碼。請原諒一長串字串。我無法快速找到可以重現該行為的較短串列。
編譯器資源管理器同意 GCC 10 及更高版本的段錯誤。
這是編譯器錯誤還是我在這里遺漏了一些明顯的東西?
#include <unordered_map>
#include <vector>
#include <algorithm>
#include <string>
int main(int argc, char** argv) {
std::unordered_map<
std::string,
int
> terms;
std::vector<const char*> input {
"Head", "of", "Data", "News", "UK", "We", "are", "News", "UK", "is", "a",
"great", "company", "full", "talented", "and", "creative", "people", "We",
"are", "an", "organisation", "that", "holds", "journalism", "at", "its",
"very", "heart", "Our", "newspapers", "and", "digital", "products",
"include", "some", "of", "the", "most", "powerful", "media", "brands", "in",
"the", "English", "speaking", "world:", "the", "Times", "The", "Sunday",
"Times", "and", "The", "Sun", "reaching", "30", "million", "people", "each",
"week", "Despite", "differences", "in", "audience", "and", "content", "our",
"brands", "are", "united", "by", "a", "commitment", "to", "independent",
"journalism", "that", "connects", "our", "customers"
};
for (const char* str : input) {
terms[str];
}
std::vector<std::pair<std::string,int>> order;
order.reserve(terms.size());
for (const auto& [ term, n ] : terms)
order.emplace_back(term,n);
std::sort(order.begin(), order.end(),
[](const auto& a, const auto& b) -> bool {
if (a.second > b.second) return true;
return a.first < b.first;
}
);
}
這是 gdb 的輸出:
Program received signal SIGSEGV, Segmentation fault.
__memcmp_evex_movbe () at ../sysdeps/x86_64/multiarch/memcmp-evex-movbe.S:118
118 VMOVU_MASK (%rsi), %YMM2{%k2}
(gdb) bt
#0 __memcmp_evex_movbe () at ../sysdeps/x86_64/multiarch/memcmp-evex-movbe.S:118
#1 0x00007ffff7d4d7ad in std::char_traits<char>::compare (__n=<optimized out>, __s2=<optimized out>, __s1=<optimized out>)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc -v3/include/bits/char_traits.h:385
#2 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::compare (this=<optimized out>, __str=...)
at /usr/src/debug/gcc-build/x86_64-pc-linux-gnu/libstdc -v3/include/bits/basic_string.h:3148
#3 0x000055555555b408 in std::operator< <char, std::char_traits<char>, std::allocator<char> > (__lhs="Data", __rhs=<error: Cannot access memory at address 0x72656d6f74737563>)
at /usr/include/c /12.1.0/bits/basic_string.h:3694
#4 0x00005555555573e2 in operator()<std::pair<std::__cxx11::basic_string<char>, int>, std::pair<std::__cxx11::basic_string<char>, int> > (__closure=0x7fffffffd9f7, a={...}, b={...}) at test.cc:108
#5 0x000055555555744b in __gnu_cxx::__ops::_Val_comp_iter<main(int, char**)::<lambda(const auto:1&, const auto:2&)> >::operator()<std::pair<std::__cxx11::basic_string<char>, int>, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char>, int>*, std::vector<std::pair<std::__cxx11::basic_string<char>, int> > > >(std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> &, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >) (this=0x7fffffffd9f7, __val={...},
__it={first = <error: Cannot access memory at address 0x72656d6f74737563>, second = 2449}) at /usr/include/c /12.1.0/bits/predefined_ops.h:240
#6 0x0000555555557096 in std::__unguarded_linear_insert<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char>, int>*, std::vector<std::pair<std::__cxx11::basic_string<char>, int> > >, __gnu_cxx::__ops::_Val_comp_iter<main(int, char**)::<lambda(const auto:1&, const auto:2&)> > >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Val_comp_iter<main(int, char**)::<lambda(const auto:1&, const auto:2&)> >) (__last={first = "", second = 3}, __comp=...) at /usr/include/c /12.1.0/bits/stl_algo.h:1789
#7 0x0000555555556c28 in std::__unguarded_insertion_sort<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char>, int>*, std::vector<std::pair<std::__cxx11::basic_string<char>, int> > >, __gnu_cxx::__ops::_Iter_comp_iter<main(int, char**)::<lambda(const auto:1&, const auto:2&)> > >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<main(int, char**)::<lambda(const auto:1&, const auto:2&)> >) (__first={first = "an", second = 1}, __last={first = "", second = 0}, __comp=...) at /usr/include/c /12.1.0/bits/stl_algo.h:1830
#8 0x000055555555695b in std::__final_insertion_sort<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char>, int>*, std::vector<std::pair<std::__cxx11::basic_string<char>, int> > >, __gnu_cxx::__ops::_Iter_comp_iter<main(int, char**)::<lambda(const auto:1&, const auto:2&)> > >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<main(int, char**)::<lambda(const auto:1&, const auto:2&)> >) (__first={first = "", second = 3}, __last={first = "", second = 0}, __comp=...) at /usr/include/c /12.1.0/bits/stl_algo.h:1850
#9 0x0000555555556806 in std::__sort<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char>, int>*, std::vector<std::pair<std::__cxx11::basic_string<char>, int> > >, __gnu_cxx::__ops::_Iter_comp_iter<main(int, char**)::<lambda(const auto:1&, const auto:2&)> > >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__ops::_Iter_comp_iter<main(int, char**)::<lambda(const auto:1&, const auto:2&)> >) (__first={first = "", second = 3}, __last={first = "", second = 0}, __comp=...) at /usr/include/c /12.1.0/bits/stl_algo.h:1940
#10 0x0000555555556751 in std::sort<__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char>, int>*, std::vector<std::pair<std::__cxx11::basic_string<char>, int> > >, main(int, char**)::<lambda(const auto:1&, const auto:2&)> >(__gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, __gnu_cxx::__normal_iterator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > > >, struct {...}) (__first={first = "", second = 3}, __last={first = "", second = 0}, __comp=...)
at /usr/include/c /12.1.0/bits/stl_algo.h:4853
#11 0x000055555555665c in main (argc=1, argv=0x7fffffffdfc8) at test.cc:105
uj5u.com熱心網友回復:
[](const auto& a, const auto& b) -> bool {
if (a.second > b.second) return true;
return a.first < b.first;
}
此比較器函式違反了作為嚴格弱排序比較器的要求。為了清楚起見,我將使用兩個int值,而不是 int 和字串,因為這使問題更容易理解,但如果其中一個值是字串,也會發生同樣的事情。std::string出于解釋的目的,比較兩個 int 值與比較兩個s具有相同的語意。
因此,例如,使用以下兩個值:
a={2, 4}
b={1, 2}
第一個將比較小于第二個。4 > 2比較器回傳 true。
a={1, 2}
b={2, 4}
這里也一樣。2 > 4為假,但1 < 2為真,因此比較器也回傳真。
最終結果:這里有兩個值,每個值都小于另一個值。
正如斯波克先生所說:這不合邏輯。
這是未定義的行為。
uj5u.com熱心網友回復:
正如指出的那樣,比較不滿足嚴格弱排序的要求。
您可以通過以下方式使用std::tie標頭中宣告的標準函式解決問題<utility>
std::sort(order.begin(), order.end(),
[](const auto& a, const auto& b) -> bool {
return std::tie( b.second, a.first ) < std::tie( a.second, b.first );
} );
之后,前 10 條排序記錄將如下所示
and 4
are 3
the 3
News 2
The 2
Times 2
UK 2
We 2
a 2
brands 2
請注意,大寫字母在字典順序中位于小寫字母之前。
uj5u.com熱心網友回復:
您的比較器功能不反映您的排序標準。通常,當您有一個元組作為排序鍵時,例如 (ke1, key2),當且僅當 key1 存在平局時,才會比較 key2。因此,當您比較 key2 時,您的比較器函式必須反映tie作為先決條件。所以一般來說,你的比較器看起來像:
if (a.key1 < a.key1) return true;
if (a.key1 == a.key1) /* tie case for key1 */
return a.key2 < b.key2;
return false;
所以您的比較器可能會更改為
[](const auto& a, const auto& b) -> bool {
if (a.second > b.second) return true;
if (a.second == b.second) // This reflects a tie for key1
return a.first < b.first;
return false;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/495267.html
下一篇:OpenCV中的邏輯運算
