我正在使用stl map存储从pcap文件中提取的流信息。当数据包到来时,我使用map.find来查找数据包所属的流是否存在。我必须使用map.find两次,因为从A到B的数据包和从B到A的数据包属于同一个流程。
struct FiveTuple
{
unsigned short source_port;
unsigned short dest_port;
unsigned int source_ip_addr;
unsigned int dest_ip_addr;
unsigned char transport_proto_type;
};
FiveTuple确定了一个流程。我使用FiveTuple作为地图中的关键元素。
地图是地图< FiveTuple,Flow,FlowCmp>,其中FlowCmp是一个结构,使用memcmp来查看FiveTuple a是否小于FiveTuple b,就像operator<。 为了查找数据包的流是否存在,我编写了如下代码,其中m是地图的名称,five_tuple是一个FiveTuple,其中包含从数据包中提取的信息:
auto it = m.find(five_tuple);
if( it == m.end())
{
//swap source and dest ip/port in five_tuple,
it = m.find(five_tuple);
if(it == m.end())
{
//do something
}
}
在vs2010的调试版中,结果是合理的。当我将它更改为发布版本时,我发现不是返回正确的迭代器,第二个m.find只是给了我大部分时间。我发现没有初始化问题。如何解决发布版本问题?
答案 0 :(得分:5)
好像你在FiveTuple对象上做了memcmp()。这是未定义的行为,因为FiveTuple包含尾随垃圾字节。这些尾随垃圾字节在调试版本和发行版本中是不同的,因此您得到不同的结果。您应该重写FlowCmp,以便它不使用memcmp()。
这是基于所提供的有限信息的猜测,但如果您想测试它,请尝试cout << sizeof(FiveTuple);
。我打赌你会看到sizeof(FiveTuple) > sizeof(short) + sizeof(short) + sizeof(int) + sizeof(int) + sizeof(char)
。换句话说,你的结构中有垃圾,你不应该使用memcmp。
当然,memcmp的另一个原因是不好的,因为这意味着您的代码将是不可移植的,因为它的行为将取决于您的平台的 endianess 。这本身就足以让我们不为此目的使用memcmp。