I have something strange happening when I try to insert one element in a map
main.cpp
S3Wrapper wrapper = S3Wrapper::getS3Wrapper();
int main(){
return 0;
}
So basically only the singleton is called for S3Wrapper
S3Wrapper.hpp
class S3Wrapper
{
S3Wrapper(std::string bucketName);
public:
~S3Wrapper();
static S3Wrapper &getS3Wrapper(std::string name = BUCKET_NAME);
}
and S3Wrapper.cpp
static std::map<std::string, S3Wrapper*> _wrapperMap;
S3Wrapper& S3Wrapper::getS3Wrapper(std::string name)
{
auto it = _wrapperMap.find(name);
if (it == _wrapperMap.end())
{
auto t = new S3Wrapper(name);
_wrapperMap[name] = t;
return *(_wrapperMap[name]);
}
return *(it->second);
}
When I compile I don't have any error/warning but then the program segfault:
g++ main.cpp S3Wrapper.cpp -std=c++0x -ls3 -g3
result of gdb
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7937c4a in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) bt
#0 0x00007ffff7937c4a in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x0000000000406295 in std::_Rb_tree_iterator<std::pair<std::string const, S3Wrapper*> >::operator-- (this=0x7fffffffd8b0) at /usr/include/c++/4.8/bits/stl_tree.h:204
#2 0x00000000004061f7 in std::_Rb_tree<std::string, std::pair<std::string const, S3Wrapper*>, std::_Select1st<std::pair<std::string const, S3Wrapper*> >, std::less<std::string>, std::allocator<std::pair<std::string const, S3Wrapper*> > >::_M_get_insert_unique_pos (this=0x60b580 <_wrapperMap>, __k=...) at /usr/include/c++/4.8/bits/stl_tree.h:1333
#3 0x00000000004058f5 in std::_Rb_tree<std::string, std::pair<std::string const, S3Wrapper*>, std::_Select1st<std::pair<std::string const, S3Wrapper*> >, std::less<std::string>, std::allocator<std::pair<std::string const, S3Wrapper*> > >::_M_get_insert_hint_unique_pos (this=0x60b580 <_wrapperMap>, __position=..., __k=...) at /usr/include/c++/4.8/bits/stl_tree.h:1425
#4 0x000000000040511c in std::_Rb_tree<std::string, std::pair<std::string const, S3Wrapper*>, std::_Select1st<std::pair<std::string const, S3Wrapper*> >, std::less<std::string>, std::allocator<std::pair<std::string const, S3Wrapper*> > >::_M_emplace_hint_unique<std::piecewise_construct_t const&, std::tuple<std::string const&>, std::tuple<> >(std::_Rb_tree_const_iterator<std::pair<std::string const, S3Wrapper*> >, std::piecewise_construct_t const&, std::tuple<std::string const&>&&, std::tuple<>&&) (this=0x60b580 <_wrapperMap>, __pos=...) at /usr/include/c++/4.8/bits/stl_tree.h:1673
#5 0x0000000000404d24 in std::map<std::string, S3Wrapper*, std::less<std::string>, std::allocator<std::pair<std::string const, S3Wrapper*> > >::operator[] (this=0x60b580 <_wrapperMap>, __k=...)
at /usr/include/c++/4.8/bits/stl_map.h:465
#6 0x0000000000404945 in S3Wrapper::getS3Wrapper (name=...) at S3Wrapper.cpp:55
#7 0x00000000004021e3 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at main.cpp:8
#8 0x00000000004022ce in _GLOBAL__sub_I_wrapper () at main.cpp:41
#9 0x0000000000406b7d in __libc_csu_init ()
#10 0x00007ffff7308e55 in __libc_start_main (main=0x401edc <main()>, argc=1, argv=0x7fffffffdc28, init=0x406b30 <__libc_csu_init>, fini=<optimized out>, rtld_fini=<optimized out>,
stack_end=0x7fffffffdc18) at libc-start.c:246
#11 0x0000000000401b79 in _start ()
line55: _wrapperMap[name] = t;
If I insert t in a vector I don't have any problem
This is the static initialisation fiasco: static variables defined in different translation units are initialised in an unspecified order, so there's no guarantee that _wrapperMap
is initialised before it's needed by the initialisation of wrapper
.
The best solution is to avoid static/global variables. They usually cause nothing but trouble.
If you really want global state, a safer option is to use a local static variable:
std::map<std::string, S3Wrapper*> & wrapperMap() {
static std::map<std::string, S3Wrapper*> map;
return map;
}
This is guaranteed to be initialised the first time the function is called, so there's no danger of using the map before initialisation. You may still have issues when static variables are destroyed at the end of the program.
Note that _wrapperMap
is reserved (in the global namespace) so you should choose a name without a leading underscore, or put it in a namespace.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With