#pragma pack引起 stl的map/list在insert时报错:(Suspended : Signal : SIGSEGV:Segmentation fault)


最近接手一个老项目,在老项目中使用了map/list存储缓存数据,如下:

map问题:

#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 
{ 
....
}

原因是:没有在“conf.h”文件中没有用“#pragma pack()”恢复字节对齐,导致包含“conf.h”文件的文件都是以4字节对齐,这样可能导致map insert函数报错。


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.


list问题


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;

}


 record.cpp中 
  
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


你可能感兴趣的:(C/C++)