Like the title suggests, I have a short demo program that compiles on with all of those compilers, but core dumps when ran after compiling with gcc 4.8 and gcc 4.9:
Any ideas as to why?
#include <unordered_map>
struct Foo : std::unordered_map<int,int> {
using std::unordered_map<int, int>::unordered_map;
// ~Foo() = default; // adding this allows it to work
};
struct Bar {
Bar(Foo f = {}) : _f(std::move(f)) {}
// using any of the following constructors fixes the problem:
// Bar(Foo f = Foo()) : _f(std::move(f)) {}
// Bar(Foo f = {}) : _f(f) {}
Foo _f;
};
int main() {
Bar b;
// the following code works as expected
// Foo f1 = {};
// Foo f2 = std::move(f1);
}
My compilation settings:
g++ --std=c++11 main.cpp
Here is a backtrace from GDB:
#0 0x00007fff95d50866 in __pthread_kill ()
#1 0x00007fff90ba435c in pthread_kill ()
#2 0x00007fff8e7d1bba in abort ()
#3 0x00007fff9682e093 in free ()
#4 0x0000000100002108 in __gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::deallocate ()
#5 0x0000000100001e7d in std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*> >::deallocate ()
#6 0x0000000100001adc in std::__detail::_Hashtable_alloc<std::allocator<std::__detail::_Hash_node<std::pair<int const, int>, false> > >::_M_deallocate_buckets ()
#7 0x000000010000182e in std::_Hashtable<int, std::pair<int const, int>, std::allocator<std::pair<int const, int> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_deallocate_buckets ()
#8 0x000000010000155a in std::_Hashtable<int, std::pair<int const, int>, std::allocator<std::pair<int const, int> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::~_Hashtable ()
#9 0x000000010000135c in std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, int> > >::~unordered_map ()
#10 0x00000001000013de in Foo::~Foo ()
#11 0x0000000100001482 in Bar::~Bar ()
#12 0x0000000100001294 in main ()
*** error for object 0x1003038a0: pointer being freed was not allocated
***
Bar(Foo f = {Foo()}) : _f(std::move(f)) {}
– Frum{}
andstd::unordered_map
constructors/destructors) – Scorpionerror: converting to 'Foo {aka std::unordered_map<int, int>}' from initializer list would use explicit constructor
– AmaletaFoo
is being called twice – Zarf{}
instead of using the default argument, and those two should be the same; yet this one runs fine but the other one crashes. – Langdonstd::move
– Zarf~Foo() = default;
allows it to work. – AmaletaBar(Foo f = {{1,2}})
, works for me, apparently when the initializer_list is empty you got problem with the allocation and deallocation. I don't know if it's a real bug or not, I would like to know what the libstdc++ team has to say about this. – Zarff
and_f
bar are not the same object. Once thestd::move
completes, there should be no guts inf
to destruct. Or am I mistaken? – Frumunordered_map
is designed to work;std::move
is a cast, that cast triggers theT&&
signature for the constructor, it's all about what happens inside the constructor. My guess is that the case with an empty it's not being handled that well because if you provide even just 1 pair it works. In general you can't say anything for sure when you just have a cast likestd::move
, the constructor is the big?
here . – ZarfFoo f = {}
is the culprit. Here it is. It's probably unrelated, though. If so, ignore my comment. – Ehrsam~Foo() = default;
fixes the problem, It very well could be the compiler driver. – AmaletaI'm not sure why I first thought it was with libstdc++, but after realizing that just adding that explicitly defined default destructor fixed it, I couldn't imagine it being the library.
I have to agree, I don't think it has to do with unordered_map. See this and this. I may be wrong though. – Ehrsam