在一些代碼,我有型PlayerObjectstd :: list :: sort與自定義比較器的分段錯誤?
std::list<PlayerObject> unknownPlayers;
的對象鏈接列表,我需要根據某些屬性的對象進行排序,所以我用類
class CountCmp
: public std::binary_function< PlayerObject, PlayerObject, bool >
{
public:
result_type operator()(const first_argument_type & lhs,
const second_argument_type & rhs) const
{
return lhs.posCount() < rhs.posCount();
}
};
通過
unknownPlayers.sort(PlayerObject::CountCmp());
但由於某種原因程序正在接收SEGV。我用-fsanitize=address
編譯標誌來研究和堆棧跟蹤像:
ASAN:SIGSEGV
=================================================================
==8521==ERROR: AddressSanitizer: SEGV on unknown address 0x0003000003e8 (pc 0x7fe7ca6d6540 bp 0x7fff07c51720 sp 0x7fff07c516e8 T0)
#0 0x7fe7ca6d653f in std::__detail::_List_node_base::_M_transfer(std::__detail::_List_node_base*, std::__detail::_List_node_base*) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x9e53f)
#1 0x881e58 in std::__cxx11::list<rcsc::PlayerObject, std::allocator<rcsc::PlayerObject> >::_M_transfer(std::_List_iterator<rcsc::PlayerObject>, std::_List_iterator<rcsc::PlayerObject>, std::_List_iterator<rcsc::PlayerObject>) /usr/include/c++/5/bits/stl_list.h:1747
#2 0x87f79f in std::__cxx11::list<rcsc::PlayerObject, std::allocator<rcsc::PlayerObject> >::splice(std::_List_const_iterator<rcsc::PlayerObject>, std::__cxx11::list<rcsc::PlayerObject, std::allocator<rcsc::PlayerObject> >&&, std::_List_const_iterator<rcsc::PlayerObject>) /usr/include/c++/5/bits/stl_list.h:1444
#3 0x87d22e in std::__cxx11::list<rcsc::PlayerObject, std::allocator<rcsc::PlayerObject> >::splice(std::_List_const_iterator<rcsc::PlayerObject>, std::__cxx11::list<rcsc::PlayerObject, std::allocator<rcsc::PlayerObject> >&, std::_List_const_iterator<rcsc::PlayerObject>) /usr/include/c++/5/bits/stl_list.h:1464
#4 0x87d90c in void std::__cxx11::list<rcsc::PlayerObject, std::allocator<rcsc::PlayerObject> >::sort<rcsc::PlayerObject::CountCmp>(rcsc::PlayerObject::CountCmp) (/home/felipe_coimbra/.../sample_player+0x87d90c)
#5 0x86c3e3 in rcsc::WorldModel::localizePlayers(rcsc::VisualSensor const&) /home/felipe_coimbra/.../world_model.cpp:2412
#6 0x864b37 in rcsc::WorldModel::updateAfterSee(rcsc::VisualSensor const&, rcsc::BodySensor const&, rcsc::ActionEffector const&, rcsc::GameTime const&) /home/felipe_coimbra/.../world_model.cpp:910
#7 0x81a7ac in rcsc::PlayerAgent::Impl::analyzeSee(char const*) /home/felipe_coimbra/.../player_agent.cpp:1552
#8 0x819b52 in rcsc::PlayerAgent::parse(char const*) /home/felipe_coimbra/.../player_agent.cpp:1393
#9 0x816519 in rcsc::PlayerAgent::handleMessage() /home/felipe_coimbra/.../player_agent.cpp:886
#10 0x75b3a8 in rcsc::BasicClient::runOnline(rcsc::SoccerAgent*) /home/felipe_coimbra/.../basic_client.cpp:158
#11 0x75ac9e in rcsc::BasicClient::run(rcsc::SoccerAgent*) /home/felipe_coimbra/.../basic_client.cpp:93
#12 0x5e933e in main /home/felipe_coimbra/.../main_player.cpp:102
#13 0x7fe7c9d6f82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#14 0x5e8ed8 in _start (/home/felipe_coimbra/.../sample_player+0x5e8ed8)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 std::__detail::_List_node_base::_M_transfer(std::__detail::_List_node_base*, std::__detail::_List_node_base*)
==8521==ABORTING
在我看來,比較好的是嚴格弱排序。那麼在std :: list :: sort中會出現段錯誤的其他可能原因是什麼?
編輯1:
我試着用list::iterator
和list::reverse_iterator
只是排序前tranverse unknownPlayers
並能正常工作。我甚至可以通過posCount()方法訪問值,並且返回的值沒有任何異常。
編輯2:
我一直在試圖挑選相關的代碼後,但我發現它有點麻煩。 我想unknownPlayers一些相關的事實是:
它是由
std::list::splice
方法填充:unknownPlayers.splice(unknownPlayers.end(), new_unknown_players);
new_unknown_players
也被splice
填補。基本上在每個遊戲週期都有關於所看到的玩家的新信息,並且這些玩家可以被識別爲隊友,對手或者根本不識別(未知玩家)。嘗試通過接近度閾值將未識別的玩家與先前識別的玩家(隊友或對手)進行匹配,如果失敗,則將他們拼接成new_unknown_players鏈接列表。
sort
也不會崩潰以同樣的方式,如果我嘗試拼接的中的代碼行上述但是該呼叫之前unknownPlayers排序,
sort
不會崩潰而unknownPlayers
是空的(感謝上帝,它不是這樣搞砸了),第一次splice
實際上增加了新的對象,並使其第一次非空。
也許這意味着在代碼的其他部分有東西正在破壞列表?我仍然無法理解爲什麼轉換可以。
這部分代碼的:
//////////////////////////////////////////////////////////////////
// splice temporary seen players to memory list
// temporary lists are cleared
M_teammates.splice(M_teammates.end(),
new_teammates);
M_opponents.splice(M_opponents.end(),
new_opponents);
// I've put some debug in this line
M_unknown_players.splice(M_unknown_players.end(),
new_unknown_players);
// And here too
/////////////////////////////////////////////////////////////////
// create team member pointer vector for sort
PlayerPtrCont all_teammates_ptr;
PlayerPtrCont all_opponents_ptr;
{
const PlayerCont::iterator end = M_teammates.end();
for (PlayerCont::iterator it = M_teammates.begin();
it != end;
++it) {
all_teammates_ptr.push_back(&(*it));
}
}
{
const PlayerCont::iterator end = M_opponents.end();
for (PlayerCont::iterator it = M_opponents.begin();
it != end;
++it) {
all_opponents_ptr.push_back(&(*it));
}
}
/////////////////////////////////////////////////////////////////
// sort by accuracy count
std::sort(all_teammates_ptr.begin(),
all_teammates_ptr.end(),
PlayerObject::PtrCountCmp());
std::sort(all_opponents_ptr.begin(),
all_opponents_ptr.end(),
PlayerObject::PtrCountCmp());
// I've put some more debug here
M_unknown_players.sort(PlayerObject::CountCmp());
// And here
可以調用'posCount'和/或列表拼接以某種方式影響它將在下次輸出的值嗎? –
@MikhailMaltsev posCount函數只是一個getter:'int posCount const {return pos_count; ''。我不認爲這可能會造成干擾。 –
也許列表已損壞?例如,如果你嘗試在排序之前從'begin'到'end'和'rbegin'遍歷'rend',它會發生段錯誤嗎? –