c++ - std::bad_alloc when inserting into std::unordered_map? -
i'm getting std::bad_alloc following code:
typedef std::unordered_map<chash, block_extended_info> map_type; map_type m_foo; // transgressor: auto r = m_foo.insert(map_type::value_type(id, bei));
it happens of time while running test cases use method containing line, , other times doesn't. had changed code use m_foo[id] = bei
, caused stop happening 1 compilation, when recompiled again failed, changed above, continued fail. issue deeper that.
i sure it's not matter of running out of memory since have top
running while test cases running , doesn't anywhere near filling memory.
what may causing std::bad_alloc? in details of chash
, block_extended_info
may causing this? objects of types copied , passed around on place in other parts of code , doesn't cause issues.
here's definition of chash
:
class chash { char data[32]; };
and following required define block_extended_info
:
class csignature { chash c, r; }; enum foob { /* ... */ }; class ct { uint64_t a, b; foob c; }; typedef boost::variant< /* structs ints, maps, vectors of ints */ > txin_v; typedef boost::variant< /* similar structs */ > txout_target_v; struct tx_out { uint64_t a; txout_target_v b; }; class transaction_prefix { public: size_t version; uint64_t unlock_time; std::vector<uint8_t> extra; protected: std::vector<txin_v> a; std::vector<tx_out> b; std::vector<ct> c; std::vector<ct> d; }; class transaction: public transaction_prefix { public: std::vector<std::vector<csignature> > signatures; }; struct block_header { uint8_t major_version; uint8_t minor_version; uint64_t timestamp; chash prev_id; uint32_t nonce; }; struct block: public block_header { transaction miner_tx; std::vector<chash> tx_hashes; uint16_t food_id; csignature food_sig; }; struct block_extended_info { block bl; uint64_t height; size_t block_cumulative_size; uint64_t cumulative_difficulty; uint64_t already_generated_coins; };
stepping around relevant area in gdb, here latest few lines lead bad_alloc:
cryptonote::transaction::transaction(cryptonote::transaction const&) () @ /usr/include/c++/4.8/bits/stl_vector.h:313 313 { this->_m_impl._m_finish = 646 { return size_type(this->_m_impl._m_finish - this->_m_impl._m_start); } 91 : _tp_alloc_type(__a), _m_start(0), _m_finish(0), _m_end_of_storage(0) 168 { return __n != 0 ? _m_impl.allocate(__n) : 0; } 183 this->_m_impl._m_end_of_storage = this->_m_impl._m_start + __n; 181 this->_m_impl._m_start = this->_m_allocate(__n); 182 this->_m_impl._m_finish = this->_m_impl._m_start; 183 this->_m_impl._m_end_of_storage = this->_m_impl._m_start + __n; 310 vector(const vector& __x) 117 __uninit_copy(__first, __last, __result); cryptonote::tx_out* std::__uninitialized_copy<false>::__uninit_copy<__gnu_cxx::__normal_iterator<cryptonote::tx_out const*, std::vector<cryptonote::tx_out, std::allocator<cryptonote::tx_out> > >, cryptonote::tx_out*>(__gnu_cxx::__normal_iterator<cryptonote::tx_out const*, std::vector<cryptonote::tx_out, std::allocator<cryptonote::tx_out> > >, __gnu_cxx::__normal_iterator<cryptonote::tx_out const*, std::vector<cryptonote::tx_out, std::allocator<cryptonote::tx_out> > >, cryptonote::tx_out*) () @ /usr/include/c++/4.8/bits/stl_uninitialized.h:68 68 __uninit_copy(_inputiterator __first, _inputiterator __last, 74 (; __first != __last; ++__first, ++__cur) 83 } cryptonote::transaction::transaction(cryptonote::transaction const&) () @ /usr/include/c++/4.8/bits/stl_vector.h:313 313 { this->_m_impl._m_finish = 646 { return size_type(this->_m_impl._m_finish - this->_m_impl._m_start); } 91 : _tp_alloc_type(__a), _m_start(0), _m_finish(0), _m_end_of_storage(0) 646 { return size_type(this->_m_impl._m_finish - this->_m_impl._m_start); } 168 { return __n != 0 ? _m_impl.allocate(__n) : 0; } 101 if (__n > this->max_size()) 104 return static_cast<_tp*>(::operator new(__n * sizeof(_tp))); 183 this->_m_impl._m_end_of_storage = this->_m_impl._m_start + __n; 181 this->_m_impl._m_start = this->_m_allocate(__n); 182 this->_m_impl._m_finish = this->_m_impl._m_start; 183 this->_m_impl._m_end_of_storage = this->_m_impl._m_start + __n; 310 vector(const vector& __x) 74 (; __first != __last; ++__first, ++__cur) 71 _forwarditerator __cur = __result; 75 { ::new(static_cast<void*>(__p)) _t1(std::forward<_args>(__args)...); } 748 ++_m_current; 74 (; __first != __last; ++__first, ++__cur) 313 { this->_m_impl._m_finish = 646 { return size_type(this->_m_impl._m_finish - this->_m_impl._m_start); } 91 : _tp_alloc_type(__a), _m_start(0), _m_finish(0), _m_end_of_storage(0) 646 { return size_type(this->_m_impl._m_finish - this->_m_impl._m_start); } 168 { return __n != 0 ? _m_impl.allocate(__n) : 0; } 183 this->_m_impl._m_end_of_storage = this->_m_impl._m_start + __n; 181 this->_m_impl._m_start = this->_m_allocate(__n); 182 this->_m_impl._m_finish = this->_m_impl._m_start; 183 this->_m_impl._m_end_of_storage = this->_m_impl._m_start + __n; 310 vector(const vector& __x) 74 (; __first != __last; ++__first, ++__cur) 570 class transaction: public transaction_prefix 313 { this->_m_impl._m_finish = 646 { return size_type(this->_m_impl._m_finish - this->_m_impl._m_start); } 91 : _tp_alloc_type(__a), _m_start(0), _m_finish(0), _m_end_of_storage(0) 646 { return size_type(this->_m_impl._m_finish - this->_m_impl._m_start); } 168 { return __n != 0 ? _m_impl.allocate(__n) : 0; } 101 if (__n > this->max_size()) 104 return static_cast<_tp*>(::operator new(__n * sizeof(_tp))); 181 this->_m_impl._m_start = this->_m_allocate(__n); 183 this->_m_impl._m_end_of_storage = this->_m_impl._m_start + __n; 181 this->_m_impl._m_start = this->_m_allocate(__n); 182 this->_m_impl._m_finish = this->_m_impl._m_start; 183 this->_m_impl._m_end_of_storage = this->_m_impl._m_start + __n; 310 vector(const vector& __x) 74 (; __first != __last; ++__first, ++__cur) 101 if (__n > this->max_size()) 75 { ::new(static_cast<void*>(__p)) _t1(std::forward<_args>(__args)...); } 646 { return size_type(this->_m_impl._m_finish - this->_m_impl._m_start); } 91 : _tp_alloc_type(__a), _m_start(0), _m_finish(0), _m_end_of_storage(0) 168 { return __n != 0 ? _m_impl.allocate(__n) : 0; } 101 if (__n > this->max_size()) 102 std::__throw_bad_alloc();
as πάντα ῥεῖ suspected, problem elsewhere.
the code listed in function called add_block_as_invalid(...)
. call site looked this:
// parameter, iterators m_alternative_chains std::list<blocks_ext_by_hash::iterator>& alt_chain; for(auto alt_ch_iter = alt_chain.begin(); alt_ch_iter != alt_chain.end(); alt_ch_iter++) { // .... auto ch_ent = *alt_ch_iter; // .... m_alternative_chains.erase(ch_ent); for(auto alt_ch_to_orph_iter = ++alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end(); alt_ch_to_orph_iter++) { add_block_as_invalid((*alt_ch_iter)->second, (*alt_ch_iter)->first); m_alternative_chains.erase(*alt_ch_to_orph_iter); } }
the call add_block_as_invalid
kept dereferencing alt_ch_iter
, had been erased.
Comments
Post a Comment