在项目的开发中,使用[]设置map变量时,出现了Segment Fault的问题,使用GDB bt命令得到调用栈(中间部分被我去掉了)如下:
#0 0x00000000008da74a in std::local_Rb_tree_decrement(std::_Rb_tree_node_base*) ()
Missing separate debuginfos, use: debuginfo-install cyrus-sasl-lib-2.1.26-20.el7_2.x86_64 glibc-2.17-196.el7_4.2.x86_64 gperftools-libs-2.4-8.el7.x86_64 keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-8.el7.x86_64 libcom_err-1.42.9-10.el7.x86_64 libcurl-7.29.0-42.el7_4.1.x86_64 libgcc-4.8.5-16.el7_4.2.x86_64 libidn-1.28-4.el7.x86_64 libselinux-2.5-11.el7.x86_64 libssh2-1.4.3-10.el7_2.1.x86_64 libstdc++-4.8.5-16.el7_4.2.x86_64 libunwind-1.1-5.el7_2.2.x86_64 mariadb-libs-5.5.56-2.el7.x86_64 nspr-4.13.1-1.0.el7_3.x86_64 nss-3.28.4-15.el7_4.x86_64 nss-softokn-freebl-3.28.3-8.el7_4.x86_64 nss-util-3.28.4-3.el7.x86_64 openldap-2.4.40-13.el7.x86_64 openssl-libs-1.0.2k-8.el7.x86_64 pcre-8.32-17.el7.x86_64 zlib-1.2.7-17.el7.x86_64
(gdb) bt
#0 0x00000000008da74a in std::local_Rb_tree_decrement(std::_Rb_tree_node_base*) ()
#1 0x0000000000823083 in operator-- (this=<synthetic pointer>) at /usr/include/c++/4.8.2/bits/stl_tree.h:204
#2 std::_Rb_tree<unsigned int, std::pair<unsigned int const, std::map<unsigned int, int, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, int> > > >, std::_Select1st<std::pair<unsigned int const, std::map<unsigned int, int, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, int> > > > >, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, std::map<unsigned int, int, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, int> > > > > >::_M_get_insert_unique_pos
(this=this@entry=0x7fe6cdb45a9c, __k=@0x3a82300: 3) at /usr/include/c++/4.8.2/bits/stl_tree.h:1333
#3 0x000000000082315b in std::_Rb_tree<unsigned int, std::pair<unsigned int const, std::map<unsigned int, int, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, int> > > >, std::_Select1st<std::pair<unsigned int const, std::map<unsigned int, int, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, int> > > > >, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, std::map<unsigned int, int, std::less<unsigned int>, std::allocator<std::pair<unsigned int const, int> > > > > >::_M_get_insert_hint_unique_pos (this=this@entry=0x7fe6cdb45a9c, __position=..., __position@entry=..., __k=@0x3a82300: 3) at /usr/include/c++/4.8.2/bits/stl_tree.h:1441
#4 0x00000000008212f1 in _M_emplace_hint_unique<const std::piecewise_construct_t&, std::tuple<unsigned int const&>, std::tuple<> > (__pos=..., this=0x7fe6cdb45a9c) at /usr/include/c++/4.8.2/bits/stl_tree.h:1673
#5 operator[] (__k=<synthetic pointer>, this=0x7fe6cdb45a9c) at /usr/include/c++/4.8.2/bits/stl_map.h:465
...
...
...
#13 0x000000000047f380 in ApplicationBase::Run (this=0xf789e0 <Singleton<Application>::get_instance()::t>) at commlib/application_base.cpp:176
#14 0x00007fe6e15abc05 in __libc_start_main () from /lib64/libc.so.6
#15 0x0000000000443707 in _start ()
一开始遇到这个问题是懵逼的,因为觉得自己的做法是没问题的,虽然用的是map中嵌套了map:
std::map<uint32_t, std::map<uint32_t, int32_t> > group_chess_;
但看了下项目其他地方也有用到map嵌套map的,也是通过两个[]进行赋值,并没有出现Segment Fault的情况。通过网上搜索了下,找到下面两个链接:
static的map成员的初始化顺序居然和编译器相关
全局变量相互依赖和初始化顺序的解决办法
然后发现自己在赋值之前,还通过group_chess_.find(id)操作对其进行操作,猜测可能是自己先find操作,导致对group_chess_的一些重要内容没有进行初始化,从而赋值出错。便在类的构造函数里面执行了这项操作:group_chess_.clear()。结果问题就解决了。
看来的确是因为提前find操作导致部分内容没有被初始化,接下来想看看侯捷的《STL源码剖析》了解下为什么,希望能找到答案,也是深入了解下STL。
-------------------------------------------------------------------------------------------------------------------------------------------------
2019.4.17更新
跟随调用栈看了下STL的源码,发现find并没有做特殊的操作,并且[]操作也是有申请空间的。
搜索答案时找到也有小哥遇到同样问题,并且也是同样的clear就可以了,链接如下:
Why would an empty std::map seg fault on the first insert?
自己简单写了代码测试下:
#include <map>
class Test{
private:
int ii;
std::map<int, std::map<int, int> > inner;
public:
Test() {
ii = 0;
}
void Set(int i) {
if (inner.find(i) == inner.end()) {
inner[i][i] = i;
}
}
};
int main() {
Test test;
test.Set(1);
test.Set(2);
test.Set(3);
return 0;
}
测试中并没有出现Segment Fault,定位过程中看到下面这篇文章:
#pragma pack引起 stl的map/list在insert时报错:(Suspended : Signal : SIGSEGV:Segmentation fault)
虽然在项目其他头文件中有用到#pragma pack,但是都是成对的,并且出问题的类中头文件没有用到这个。所以应该不是这个问题导致的。目前怀疑是编译的时候某些选项导致的吧,接下来看下能怎么定位了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)