最近接手一个老项目,在老项目中使用了map/list存储缓存数据,如下:
#include "conf.h"
int Frame::parse()
{
std::map tmpString;
tmpString.insert(std::map::value_type(string("0000"), 12123323));
tmpString.insert(std::map::value_type(string("1111"), 54678456)); //Crashes here.
tmpString.insert(std::map::value_type(string("2222"), 45654548));
}
结果发现每次在insert第二次时程序core。
堆栈如下:
Thread [3] 29672 [core: 2] (Suspended : Signal : SIGSEGV:Segmentation fault)
std::basic_string, std::allocator >::compare(std::basic_string, std::allocator > const&) const at 0x354669c47d
std::operator< , std::allocator >() at basic_string.h:2,317 0x449d91
std::less, std::allocator > >::operator() at stl_function.h:230 0x44a46b
std::_Rb_tree, std::allocator >, std::pair, std::allocator > const, unsigned long>, std::_Select1st, std::allocator > const, unsigned long> >, std::less, std::allocator > >, std::allocator, std::allocator > const, unsigned long> > >::_M_insert_unique() at stl_tree.h:1,170 0x44ef40
std::map, std::allocator >, unsigned long, std::less, std::allocator > >, std::allocator, std::allocator > const, unsigned long> > >::insert() at stl_map.h:500 0x44e9f5
Frame::parse() at AnySDFrame.cpp:220 0x44df6b
查找了一上午也没找到原因。最后在stackoverflow中找到了相同的问题,结果找到了原因。
在“conf.h”文件中,我定义了一些结构体,并使用了#pragma pack(4)来设置结构体内存对齐,如下:
#include
#pragma pack (4)
typedef struct
{
....
}
stackoverflow中也说明了器错误的应用头文件,导致了这一问题:
Problem solved.
Thought I'd add it here on the off chance anyone else ever does the same thing.
I slowly removed files in my project to try and find the offending file. I was thinking that it must be something defined in a header file that was causing issues (like a static). It took a long time but I think I've found it. I had a header file that defines a number of structs. These are serialized to the wire so I had them 1 byte aligned using #pragma pack (push) which I put at the top of the file and #pragma pack (pop) at the bottom. But I then added a couple of #include statements after the first #pragma definition meaning that these includes were aligned incorrectly and caused some nondeterministic behavior. Thanks everyone that had a look. Should probably use the attribute syntax and I wouldn't had the problem. Offending code is below for completeness.
例如下代码:
#pragma pack (push)
#pragma pack (1)
#include //Wrong place for includes!
#include
typedef struct
{
....
}
#pragma pack (pop)
Thanks to everyone who had a look at initial problem.
conf.h中
#pragma pack(4)
namespace SEND_DATA{
struct send_1{
...
}
struct send_2{
...
}
}
#pragma pack()
record.h中
#include "conf.h"
#pragma pack(4)
namespace RECODE{
struct a1{
...
}
struct a2{
...
}
}
#pragma pack()
using namespace RECODE;
using namespace SEND_DATA;
class record {
public:
list my_record;
list my_send;
}
send_1 s1;
s1.* = *; //初始化
my_send.push_back() //报错
堆栈:
Program terminated with signal 11, Segmentation fault.
#0 0x0000003546663843 in std::_List_node_base::hook(std::_List_node_base*) ()
from /usr/lib64/libstdc++.so.6
Missing separate debuginfos, use: debuginfo-install cyrus-sasl-lib-2.1.23-13.el6.x86_64 glibc-2.12-1.47.el6.x86_64 keyutils-libs-1.4-3.el6.x86_64 krb5-libs-1.9-22.el6.x86_64 libcom_err-1.41.12-11.el6.x86_64 libcurl-7.19.7-40.el6_6.1.x86_64 libgcc-4.4.6-3.el6.x86_64 libidn-1.18-2.el6.x86_64 libselinux-2.0.94-5.2.el6.x86_64 libssh2-1.4.2-1.el6.x86_64 libstdc++-4.4.6-3.el6.x86_64 nspr-4.10.6-1.el6_5.x86_64 nss-3.16.1-14.el6.x86_64 nss-softokn-freebl-3.14.3-17.el6.x86_64 nss-util-3.16.1-3.el6.x86_64 openldap-2.4.23-20.el6.x86_64 openssl-1.0.1e-16.el6_5.7.x86_64 zlib-1.2.3-29.el6.x86_64
(gdb) where
#0 0x0000003546663843 in std::_List_node_base::hook(std::_List_node_base*) ()
from /usr/lib64/libstdc++.so.6
#1 0x000000000041ace6 in std::list >::_M_insert (this=0x7fa8717fab0c, __position=..., __x=...)
at /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h:1408
#2 0x000000000041a148 in std::list >::push_back (this=0x7fa8717fab0c, __x=...)
at /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h:920
解决方法:
将record.h中的class record包含在#pragma pack()内,就能运行正常。
原因可能是,虽然conf.h中的struct已经被#pragma pack()设置为4字节对齐,但是在编译class record时,也需要设置类的对齐方式。
而my_record没有报错,可能是c_record的定义是在相同的record.h文件中,所以正常吧。这是猜想-_-
哎,所以,使用#pragma pack()需谨慎啊!!!
http://stackoverflow.com/questions/13153047/memory-corruption-due-to-pragma-pack-error-std-map-corruption-crashing-on-in